Codeforces Round #578 (Div. 2) E. Compress Words ###K ###K //K

题目链接:https://codeforces.ml/problemset/problem/1200/E

题意:给定n个字符串 总长度不超过1e6   每个字符串从头到尾可以合并 要找到最大的i,满足第一个单词的长度为i的后缀和第二个单词长度为i的前缀相等 然后重复的部分只取一遍合并

思路:考虑 暴力 枚举长度 然后慢慢匹配的话要n^2  那么考虑用kmp来匹配来优化,每次匹配的话最多只会匹配到下一个字符串的长度

所以最终匹配的长度最多为1e6 并且kmp匹配 o n  所以复杂度没有问题  所以直接对ans 匹配即可  最后的j剩下多少就证明s有多少前缀和ans的后缀重合了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e6+10;
 4 const int mod=1e9+7;
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define pi pair<int,int>
 8 #define fi first
 9 #define sc second
10 #define pb push_back
11 
12 
13 int nxt[maxn];
14 
15 int main()
16 {
17     ios::sync_with_stdio(false);
18     cin.tie(0);
19     int t;
20     cin>>t;
21     string ans;
22     cin>>ans;
23     t--;
24     while(t--)
25     {
26         string s;
27         cin>>s;
28         int n=s.size();
29         s=' '+s;
30         for(int i=2,j=0;i<=n;i++)
31         {
32             while(j&&s[i]!=s[j+1]) j=nxt[j];
33             if(s[i]==s[j+1]) j++;
34             nxt[i]=j;
35         }
36         int m=ans.size();
37         int j=0;
38         int st=max(0,m-1-n+1);
39         for(int i=st;i<m;i++)
40         {
41             while(j&&ans[i]!=s[j+1]) j=nxt[j];
42             if(ans[i]==s[j+1]) j++;
43         }
44         ans+=s.substr(1+j,n);
45 
46     }
47     cout<<ans<<'\n';
48 
49 
50 
51 
52 
53 
54 
55 }
View Code

 

posted @ 2020-10-13 10:37  canwinfor  阅读(100)  评论(0)    收藏  举报