[kmp,不要过多调用strlen!!!] Codeforces 1200E Compress Words

匿名 (未验证) 提交于 2019-12-02 23:55:01

题目:http://codeforces.com/contest/1200/problem/E

Compress Words
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

nsample" and "please" into "samplease".

Amugae will merge his sentence left to right (i.e. first merge the first two words, then merge the result with the third word and so on). Write a program that prints the compressed word after the merging process ends.

Input

n1n1051≤n≤105), the number of the words in Amugae's sentence.

nA', 'B', ..., 'Z', 'a', 'b', ..., 'z', '0', '1', ..., '106106.

Output

In the only line output the compressed word after the merging process ends as described in the problem.

Examples
input
Copy
5 I want to order pizza 
output
Copy
Iwantorderpizza
input
Copy
5 sample please ease in out 
output
Copy
sampleaseinout

题意:

给你n个字符串,你需要按顺序连接这些字符串,如果当前的字符串的前缀和上一个字符串的后缀相同,则连接时要去掉当前字符串的前缀

˼·:

一开始暴力,果断TLE,然后用kmp,还是TLE,改了几十次后发现是每次调用kmp和getnex时都调用用了strlen,增加了复杂度,去掉之后就AC了
为什么用kmp呢?因为kmp可以在文本串中找到模板串匹配的部分,现在要当前字符串的前缀匹配上一个字符串的后缀,我们就从上一个字符串的长度-当前字符串的长度的位置开始找,
因为一个字符串的前缀最长是他本身,所以当前字符串的前缀最多能匹配到这个位置(再往前当前字符串的长度就不够了),然后用kmp匹配,然后返回一个当前字符串的前缀与上一个字符串的后缀不匹配的位置(就是return j,j是当前字符串匹配的位置,如果t[i]==p[j]则j++,所以返回时j会指向不匹配的位置)

注意:

如果调用太多次strlen会TLE!!!

 1 #include<bits/stdc++.h>  2 using namespace std;  3 const int amn=1e6+5;  4 char ans[amn],in[amn];  5 int n,nex[amn],len,tp;  6 void getnex(char in[]){     ///不要在这调用strlen!!!,用已有的就好了,不然会T到自闭!!!  7     nex[0]=nex[1]=0;  8     for(int i=1;i<len;i++){  9         int j=nex[i]; 10         while(j&&in[i]!=in[j])j=nex[j]; 11         nex[i+1]=in[i]==in[j]?j+1:0; 12     } 13 } 14 int kmp(char t[],char p[],int pos){     ///不要在这调用strlen!!!,用已有的就好了,不然会T到自闭!!! 15     getnex(in); 16     int j=0; 17     for(int i=pos;i<tp;i++){ 18         while(j&&p[j]!=t[i])j=nex[j]; 19         if(p[j]==t[i])j++; 20     } 21     return j; 22 } 23 int main(){ 24     ios::sync_with_stdio(0); 25     cin>>n; 26     cin>>ans; 27     int pos; 28     tp=strlen(ans);     ///注意,如果调用太多次strlen会TLE!!! 29     for(int i=2;i<=n;i++){ 30         cin>>in; 31         len=strlen(in); 32         pos=tp-len;     ///上一个字符串的长度-当前字符串的长度,因为一个字符串的前缀最长是他本身,他最多只能匹配到这个位置 33         for(int j=kmp(ans,in,pos);j<len;j++) 34             ans[tp++]=in[j]; 35     } 36     for(int i=0;i<tp;i++) 37         printf("%c",ans[i]); 38     printf("\n"); 39 } 40 /** 41 给你n个字符串,你需要按顺序连接这些字符串,如果当前的字符串的前缀和上一个字符串的后缀相同,则连接时要去掉当前字符串的前缀 42 一开始暴力,果断TLE,然后用kmp,还是TLE,改了几十次后发现是每次调用kmp和getnex时都调用用了strlen,增加了复杂度,去掉之后就AC了 43 为什么用kmp呢?因为kmp可以在文本串中找到模板串匹配的部分,现在要当前字符串的前缀匹配上一个字符串的后缀,我们就从上一个字符串的长度-当前字符串的长度的位置开始找, 44 因为一个字符串的前缀最长是他本身,所以当前字符串的前缀最多能匹配到这个位置(再往前当前字符串的长度就不够了),然后用kmp匹配,然后返回一个当前字符串的前缀与上一个字符串的后缀不匹配的位置(就是return j,j是当前字符串匹配的位置,如果t[i]==p[j]则j++,所以返回时j会指向不匹配的位置) 45 然后从这个位置开始把当前字符串后面的字符都加到上一个字符串后面,知道输入完毕,最后输出ans就行了 46 注意:如果调用太多次strlen会TLE!!! 47 **/

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!