给定一个自动机,最多1000个节点,问能否存在一个字符串xyz,其中x,y,z均为一个字符串,且y的长度不为空,使得xz,xyz,xyyz,xyyyz,...均能被自动机识别。
有这样的字符串的条件是,存在一个节点i,从初始态出发,到达节点i,构成了字符串x,从i出发,到达一个结束态,构成了字符串z,从i出发,走不小于一条边,回到i,构成字符串y。
所以做法是,先bfs一遍,看哪些点可以从初始态到达。再在反向图上bfs一遍,看哪些点可以到达结束态。再从每个从初始态能到的且能到结束态的点上bfs一遍,看能否回到自己。如果能,则已经找到一组答案。如果不存在这样的节点,则找不到。
最开始读错题了..当成只需要xyz,xyyz,...能被识别就可以了...于是写麻烦了好多...
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
struct Edge {
int t;
char c;
Edge *ne;
void clear(int tt,char cc,Edge *&nee) {
t=tt;c=cc;ne=nee;
nee=this;
}
};
string startx[1001];
string endz[1001];
bool st[1001]={0};
bool fin[1001]={0};
Edge b[52000],*bp;
Edge *fe[1001]={0};
Edge *rfe[1001]={0};
int from[1001];
char cf[1001];
int que[1001];
int n,s,p,q;
char str[1001];
void bfs(Edge **fe,bool opt=true) {
int i;
for (i=0;i<=n;i++) from[i]=-1;
if (opt) for (i=p;i<q;i++) from[que[i]]=-2;
while (p!=q) {
i=que[p++];
for (Edge *j=fe[i];j;j=j->ne) {
int t=j->t;
if (from[t]==-1) {
from[t]=i;
cf[t]=j->c;
que[q++]=t;
}
}
}
}
string getS(int j,bool opt=true) {
int ss=0;
while (from[j]!=-2) {
str[ss++]=cf[j];
j=from[j];
}
if (opt) {
for (int i=0;i+i<ss;i++) {
char c=str[i];
str[i]=str[ss-i-1];
str[ss-i-1]=c;
}
}
str[ss]='\0';
return string(str);
}
string getY(int j) {
int ss=0,f=j;
do {
str[ss++]=cf[j];
j=from[j];
} while (j!=f);
for (int i=0;i+i<ss;i++) {
char c=str[i];
str[i]=str[ss-i-1];
str[ss-i-1]=c;
}
str[ss]='\0';
return string(str);
}
bool canFindAns() {
for (int i=0;i<=n;i++) {
if (st[i]&&fin[i]) {
p=q=0;
que[q++]=i;
bfs(fe,false);
if (from[i]!=-1) {
printf("%s(%s)%s\n",startx[i].c_str(),getY(i).c_str(),endz[i].c_str());
return true;
}
}
}
return false;
}
void calEndZ() {
p=q=0;
for (int i=0;i<=n;i++)
if (fin[i]) que[q++]=i;
bfs(rfe);
for (int i=0;i<=n;i++) {
if (from[i]!=-1) {
fin[i]=true;
endz[i]=getS(i,false);
}
}
}
void calStartX() {
p=q=0;
que[q++]=s;
bfs(fe);
for (int i=0;i<=n;i++) {
if (from[i]!=-1) {
st[i]=true;
startx[i]=getS(i);
}
}
}
int main() {
int i,m,k;
scanf("%d%d",&n,&s);
scanf("%d",&m);
bp=b;
for (i=0;i<m;i++) {
int x,y;
char c;
scanf("%d %c%d",&x,&c,&y);
(bp++)->clear(y,c,fe[x]);
(bp++)->clear(x,c,rfe[y]);
}
scanf("%d",&k);
for (i=0;i<k;i++) {
int x;
scanf("%d",&x);
fin[x]=true;
}
st[s]=true;
calStartX();
calEndZ();
if (!canFindAns()) printf("*\n");
return 0;
}