版权声明:转载无所谓的。。。 https://blog.csdn.net/xuxiayang/article/details/82855959
大意
给定转换规则,求最小步数
思路
其实可以用AC自动机
这道题是问我们最小步数,因为其分支不大( )容易想到专门处理最优化问题的 算法
在 的匹配中,本人采用的是用字符数组模拟字符串中的运算,建立新的“ ”,然后在匹配过程中,使用 实现,对于判重,使用
代码
#include<map>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;char a[7][21],b[7][21];//转换规则串
const int base=233;//hash值
int n,ans,kmp[21];
unsigned long long zd;//目标串的hash值
map<unsigned long long,bool>m;//map库
struct String//定义一种结构体
{
char c[101];//字符串
int next[101],bs;//kmp_next数组,bs表示当前步数
inline int size(){return strlen(c);}//长度
inline void read(){scanf("%s",c);return;}//输入
inline void build()//建立next数组
{
next[0]=-1;
int j=-1;
for(register int i=1;i<strlen(c);i++)
{
while(j>-1&&c[j+1]!=c[i]) j=next[j];
if(c[j+1]==c[i]) j++;
next[i]=j;
}
return;
}
inline int find(char s[])//查找s在c中出现的所有位置,并返回子串个数,复杂度n+m
{
int j=-1,len=0;
for(register int i=0;i<strlen(c);i++)
{
while(j>-1&&s[j+1]!=c[i]) j=next[j];
if(s[j+1]==c[i]) j++;
if(j==strlen(s)-1) kmp[++len]=i-j,j=0;
}
return len;
}
inline unsigned long long hash()//自然溢出求hash值
{
unsigned long long ans=0;
for(register int i=0;i<strlen(c);i++)ans=ans*base+c[i];
return ans;
}
}Begin,End;//定义起始串和目标串
inline int bfs()
{
queue<String>q;//建立元素为结构体的队列,方便转移
q.push(Begin);//放入
while(q.size())
{
String x=q.front();x.build();q.pop();//取出并求出next数组
if(x.bs==10) continue;//超出步数不管它
for(register int i=0;i<n;i++)
{
int len=x.find(a[i]),lena=strlen(a[i]),lenb=strlen(b[i]);
if(!len) continue;//没有匹配串退出
for(register int cs=1;cs<=len;cs++)
{
String y=x;
y.bs=x.bs+1;//bs多了一步
int t=kmp[cs];//取出位置
if(lena==lenb)for(register int j=t;j<t+lena;j++) y.c[j]=b[i][j-t];//长度相同直接赋值
if(lena<lenb)//长度将变长
{
for(register int k=1;k<=lenb-lena;k++)
for(register int j=y.size()+(lenb-lena)-1;j>=t+lena;j--)
y.c[j]=y.c[j-(lenb-lena)];//将后面的往前挪长度差次
for(register int j=t;j<t+lenb;j++) y.c[j]=b[i][j-t];//转换
}
if(lena>lenb)//长度将变短
{
for(register int j=t;j<t+lenb;j++) y.c[j]=b[i][j-t];//转换
for(register int k=1;k<=lena-lenb;k++)
for(register int j=t+lenb;j<y.size();j++) y.c[j]=y.c[j+1];//将前面的往后挪长度差位
}
unsigned long long hh=y.hash();//计算hash值
if(hh==zd) return y.bs;//到达终点,返回步数
if(m.find(hh)==m.end()) q.push(y),m[hh]=true;//若没有出现过,将其入队
}
}
}
return -1;
}
signed main()
{
Begin.read();End.read();zd=End.hash();//输入
while(scanf("%s %s",a[n],b[n])!=EOF)n++;//输入
ans=bfs();//bfs
if(ans<0) printf("NO ANSWER!");
else printf("%d",ans);//输出
}