hdu 4300 Clairewd’s message (扩展KMP)

这道题问的就是将1个串如何变为stringA+stringB的形式,使得stringA是stringB经过映射得到相同的串。映射那步其实没有什么 价值,假设str为原串s经过映射后得到的串,我们可以以str为模式串,以s为原串做一次扩展KMP,得到extend数组,extend[i]表示原 串以第i开始与模式串的前缀的最长匹配。经过O(n)的枚举,我们可以得到,若extend[i]+i=len且i>=extend[i]时,表示 stringB即为该点之前的串,stringA即为该点之前的str串,最后输出即可。


#include<stdio.h> #include<string.h> #include<map> #define maxn 200000 using namespace std; map<char,char>map1; int max(int x,int y) { return x>y?x:y; } char s[maxn],tab[maxn],c[maxn]; int next[maxn],extend[maxn]; void EKMP(char s[],char t[])//s[]为主串,t[]为模版串 { int i,j,p,l; int len=strlen(t); int len1=strlen(s); memset(next,0,sizeof(next)); memset(extend,0,sizeof(extend)); next[0]=len; j=0; while(1+j<len&&t[j]==t[1+j])j++; next[1]=j; int a=1; for(i=2;i<len;i++) { p=next[a]+a-1; l=next[i-a]; if(i+l<p+1)next[i]=l; else { j=max(0,p-i+1); while(i+j<len&&t[i+j]==t[0+j])j++; next[i]=j; a=i; } } j=0; while(j<len1&&j<len&&s[j]==t[j])j++; extend[0]=j; a=0; for(i=1;i<len1;i++) { p=extend[a]+a-1; l=next[i-a]; if(l+i<p+1)extend[i]=next[i-a]; else { j=max(0,p-i+1); while(i+j<len1&&j<len&&s[i+j]==t[j])j++; extend[i]=j; a=i; } } } int main() { int i,j; int t; scanf("%d",&t); while(t--) { scanf("%s%s",tab,s); int len=strlen(tab); int len1=strlen(s); for(i=0;i<len;i++) { map1[tab[i]]='a'+i; } for(i=0;i<len1;i++) { c[i]=map1[s[i]]; } c[i]='\0'; EKMP(s,c); for(i=0;i<len1;i++) { if(i+extend[i]>=len1&&i>=extend[i]) { break; } } for(j=0;j<i;j++)printf("%c",s[j]); for(j=0;j<i;j++)printf("%c",map1[s[j]]); printf("\n"); } }

你可能感兴趣的:(message)