题意:
Amugae有n个单词,他想把这个n个单词变成一个句子,具体来说就是从左到右依次把两个单词合并成一个单词.合并两个单词的时候,要找到最大的i(i\ge 0)i(i≥0),满足第一个单词的长度为ii的后缀和第二个单词长度为ii的前缀相等,然后把第二个单词第ii位以后的部分接到第一个单词后面.输出最后那个单词。
题解:
这题事实上要我们求的是:
当前拼接好的串的后缀 和 待拼接串的前缀 的最大匹配长度。
可能有点绕,我们结合样例2来理解下。
当前拼接好的串 samplesample
待拼接串 pleaseplease
后缀和前缀的最大匹配 pleple
最大匹配长度 33
所以我们只要把 asease 加入到当前拼接好的串。
此时当前拼接好的串 sampleasesamplease
那么匹配的工作就交给KMP啦;
上板子:(小蓝书上的)
//char a[],b[],int next1[],lb=strlen(b+1),la=strlen(a+1);
void KMP(){
next1[1]=0;
for(int i=2,j=0;i<=lb;i++)
{
while(j!=0&&b[i]!=b[j+1])
j=next1[j];
if(b[i]==b[j+1])j++;
next1[i]=j;
}
}
void get_f(){
for(int i=1,j=0;i<=la;i++){
while(j>0&&(a[i]!=b[j+1]))
j=next1[j];
if(a[i]==b[j+1])
j++;
if(j==lb){
j=next1[j];
printf("%lld\n",i-lb+1);
}
}
}
完整代码如下:
/*Keep on going Never give up*/
#include <bits/stdc++.h>
using namespace std;
#define MAX 0x7fffffff
#define int long long
const int mod = 1e9+7;
const int maxn = 1e6+1000;
char a[maxn],ans[maxn];
int n,next1[maxn],anslen,mi,top;
int KMP(){
next1[1]=0;
for(int i=2,j=0;i<=top;i++)
{
while(j!=0&&a[i]!=a[j+1])
j=next1[j];
if(a[i]==a[j+1])j++;
next1[i]=j;
}
return next1[top];
}
signed main(){
scanf("%lld",&n);
for(int k=1;k<=n;k++){
scanf("%s",a+1);
int len=strlen(a+1);
top=len;
a[++top]='#';// 避免匹配到超出原串的字符;
mi=min(len,anslen);
for(int i=1;i<=mi;i++)a[++top]=ans[anslen-mi+i];
int ll=KMP();
for(int i=ll+1;i<=len;i++)ans[++anslen]=a[i];
}
for(int i=1;i<=anslen;i++)printf("%c",ans[i]);
return 0;
}
结束啦:)
div2的E题也很简单嘛(小声bb)