CF1200E Compress Words(KMP)

CF1200E Compress Words(KMP)

分析

每次让答案和新串匹配前后缀即可。

细节

  • \(n\le 10^5\),但是字符串长度是 \(\le 10^6\) 的。
  • 最大相同的前缀最多就 \(O(len)\) 个(\(len\) 是新串长度),不用每次把答案字符串扫完。

Code

#include<bits/stdc++.h>
#define sd std::
//#define int long long
#define il inline
#define db double
#define ldb long double
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define X first
#define Y second
#define kg putchar(' ')
#define Fr(a) for(auto it:a)
#define dbg(x) sd cout<<#x<<": "<<x<<sd endl
il int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
il void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
il void put(int x){print(x);putchar('\n');}
il void printk(int x){print(x);kg;}
const int N=1e6+10;
int n,p[N];
sd string ans;
char s[N];
il void solve()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	if(ans=="")
	{
		F(i,1,n) ans+=s[i];
		return;
	}
	int j=p[1]=0;
	F(i,2,n)
	{
		while(j>0&&s[j+1]!=s[i]) j=p[j];
		if(s[j+1]==s[i]) j++;
		p[i]=j;
	}
	j=0;
	int mi=MIN(ans.size(),n);
	//ans:0~ans.size()-1
	F(i,ans.size()-mi,ans.size()-1)
	{
		while(j>0&&ans[i]!=s[j+1]) j=p[j];
		if(s[j+1]==ans[i]) j++;
	}
	F(i,j+1,n) ans+=s[i];
	
}
int main()
{
	ans="";
	int T=1;
	T=read();
	while(T--) solve();
	sd cout<<ans;
    return 0;
}
posted @ 2024-12-12 21:02  _E_M_T  阅读(10)  评论(0)    收藏  举报