题意:对一个字符串进行n次操作,每次操作为将字符串中相应子串a转换为子串b,从最左开始进行,每次转换之后又从左开始,直至没有相应子串a
题解:KMP,需要对next数组有一定认识,每次找到子串之后将其替换,然后模式串的匹配位置变到匹配串被替换位置之前一位就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int next[100];
char res[20000];
void getnext(char s[])
{
next[0]=-1;
for(int i=0,j=-1;s[i]!='\0';)
{
if(j<0||s[i]==s[j])next[++i]=++j;
else j=next[j];
}
}
char src[12][100],dis[12][100];
int map[2000];
void replace(int rpos,char s[],char dr[])
{
//printf("replace(%d,%s,%s)\n",rpos,s,dr);
//system("pause");
int len1=strlen(s),len2=strlen(dr),lpos=rpos-len1,len=strlen(res);
if(len1==len2)
{
for(int i=0;dr[i];)
res[lpos++]=dr[i++];
}
else if(len1<len2)
{
int c=len2-len1,i=len+c;
res[i--]='\0';
for(;i-c>=rpos;i--)
res[i]=res[i-c];
for(i=0;dr[i];)
res[lpos++]=dr[i++];
}
else
{
int c=len1-len2;
rpos-=c;len-=c;
for(;rpos<len;rpos++)
res[rpos]=res[rpos+c];
res[len]='\0';
for(int i=0;dr[i];)
res[lpos++]=dr[i++];
}
}
void solve(char s[],char dr[])
{
memset(map,-1,sizeof(map));
getnext(s);
int i,j,len1=strlen(s),len2=strlen(dr);
for(i=0,j=0;res[i];)
{
if(j<0||res[i]==s[j])
{
map[i]=j;
j++;
i++;
}
else j=next[j];
if(j==len1)
{
replace(i,s,dr);
//printf("==>%s\n",res);
i-=len1+1;
if(i<0)
{
i=0;
j=0;
}
else
{
j=map[i];
i++,j++;
}
}
}
}
int main()
{
//freopen("data.txt","r",stdin);
int n;
while(scanf("%d",&n),n)
{
getchar();
for(int i=0;i<n;i++)
{
gets(src[i]);
gets(dis[i]);
}
memset(res,'\0',sizeof(res));
gets(res);
//printf("-->%s\n",res);
for(int i=0;i<n;i++)
{
solve(src[i],dis[i]);
//printf("---->%s\n",res);
}
printf("%s\n",res);
}
return 0;
}