脱水缩合

源代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<string>
#define INF 10000007
using namespace std;
struct Node
{
    int X,Y;
}i[6][37];
string S;
queue <string> Q;
int n,k,Sum[6]={0};
int Prime1[6]={13,11,7,5,3,2};
int Prime2[6]={17,19,23,29,31,37};
bool Flag(0),Vis1[10000007]={0},Vis2[10000007]={0};
int main() //我求的是什么,我不知道,但我求出了所有长度为n的可能的合并情况数。
{
    scanf("%d%d\n",&n,&k);
    for (int a=0;a<k;a++)
    {
        char t,t1,t2;
        t1=getchar();
        t2=getchar();
        getchar();
        t=getchar();
        Sum[t-'a']++;
        i[t-'a'][Sum[t-'a']].X=t1-'a';
        i[t-'a'][Sum[t-'a']].Y=t2-'a';
        getchar();
    }
    Q.push("a"); //字符串类型STL队列。
    Vis1[13]=Vis2[17]=true;
    while (!Q.empty()) //BFS注意条件,防止死循环。
    {
        S=Q.front();
        Q.pop();
        int L=S.length();
        if (L==n) //后面的肯定更长,跳出。
        {
            Flag=true;
            break;
        }
        char T[6]={0};
        for (int a=0;a<L;a++)
        {
            int t=S[a]-'a',T1=1,T2=1;
            for (int b=0;b<a;b++)
            {
                T[b]=S[b]; //算是string转char[]。
                T1=T1*Prime1[S[b]-'a']%INF*(b+1)%INF; //双重哈希。
                T2=T2*Prime2[S[b]-'a']%INF*(b+1)%INF;
            }
            for (int b=a+1;b<L;b++)
            {
                T[b+1]=S[b];
                T1=T1*Prime1[T[b+1]-'a']%INF*(b+2)%INF;
                T2=T2*Prime2[T[b+1]-'a']%INF*(b+2)%INF;
            }
            for (int b=1;b<=Sum[t];b++)
            {
                T[a]=i[t][b].X+'a';
                T[a+1]=i[t][b].Y+'a';
                int t1=T1,t2=T2;
                T1=T1*Prime1[T[a]-'a']%INF*(a+1)%INF*Prime1[T[a+1]-'a']%INF*(a+2)%INF;
                T2=T2*Prime2[T[a]-'a']%INF*(a+1)%INF*Prime2[T[a+1]-'a']%INF*(a+2)%INF;
                if (!Vis1[T1]||!Vis2[T2])
                {
                    string s(T); //char[]转string。
                    Vis1[T1]=Vis2[T2]=true;
                    Q.push(s);
                }
                T1=t1;
                T2=t2;
            }
        }
    }
    if (Flag) //特判。
      printf("%d",Q.size()+1);
    else
      printf("0");
    return 0;
}

/*
    倒着来,从"a"开始不断分裂,BFS所有情况即可。
    读题还是要细心认真,不要吝惜时间。
    血(WA)的教训!
*/
posted @ 2016-11-09 18:14  前前前世。  阅读(464)  评论(0编辑  收藏  举报