codeforces 1200 E. Compress Words(不同字符串最大前缀后缀相同长度)

https://codeforces.com/contest/1200/problem/E

题意:给出n个单词,可以把每个单词前缀后缀相同的部分合并,求最后合并单词

kmp模板题… 比赛的时候自己没有模板,网上随便找了个模板,改到最后tle,没有时间了,原因还是因为记不清楚kmp算法了,通过这道题复习了下。

思路:从第二个开始字符串开始和前面合并的子串进行kmp算法
注意每次匹配的起点位置,应该为 文本串长度-模式串长度

#include
#include
#define fi first
#define se second
#define show(a) cout<
#define show2(a,b) cout<
#define show3(a,b,c) cout<
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
using namespace std;
 
typedef long long ll;
typedef pair<int, int> P;
typedef pair<P, int> LP;
const ll inf = 1e17 + 10;
const int N = 1e6 + 100;
const ll mod = 10007;
const int base=131;
tr1::unordered_map<ll,ll> mp;
 
char a[N],b[N],ans[N];
int nx[N];
int n, m;
int l1,l2;
 
void getnext(){
    int k = -1, j = 0;
    nx[0] = -1;
    while(j < m){
        if(k == -1 || b[j] == b[k]) nx[++j] = ++k;
        else k = nx[k];
    }
}
int KMP(int st)
{
    int i,j;
    getnext();
    for(i=st,j=0;i<n;i++)
    {
    	while(j>0&&b[j]!=a[i]) j=nx[j];//匹配不成功 跳转到nx
    	if(a[i]==b[j]) j++;
    	if(j==m) return m;
    }
    return j;
}
 
int main()
{
	int t;
	scanf("%d",&t);
 
	scanf("%s",a);
	n=strlen(a);
	t--;
	int pos=0;
	for(int i=1;i<=t;i++)
	{
		scanf("%s",b);
		m=strlen(b);
		int x=KMP(max(pos-m,0));
		//show2(i,x)
 
		for(int i=x;i<m;i++)
		{
			a[n++]=b[i];
		}
		pos=n;
 
 
	}
	a[n]='\0';
	printf("%s\n",a);
 
 
}

你可能感兴趣的:(kmp,模板)