bzoj 1212 [HNOI2004] L语言(不用AC自动机)

网上的题解大多树都要建一棵trie树,并在上面跑AC自动机,然而这里有一种同样需要trie树,但时间复杂度较低的方法。

首先,我们可以轻松列出状态转移方程 F[x]=∑| F[x-len(i)]&(is(i->x,s[i]);

这样的复杂度是O(m*lens*∑len[i]*n),可能会超时,再加上hash之类的就可以过了,但这显然不优美。

====================分割线====================

对于每个F(i),我们都是从之前的额某个F(j)转移过来的,它是true当且仅当(j+1->i)是一个单词,且f[j]是true,那么我们将每个单词反过来建一棵trie树,例如有单词abc,我们将cba插入trie树,从i开始i先匹配到每个单词的最后一位,然后再匹配到最后一位相同的倒数第二位,如此下去,当我们匹配到一个单词的开头时,并且此时的F[i-depth]为true的话,F(i)就为true了,因为每个字符在trie树上的路径唯一,且trie树的深度不超过单词的最长长度(10),所以它的复杂度还是非常可看的,复杂度为O(m*lens*dep(trie))=O(m*lens*max(strlen(word))),20*1M*10,轻松过。

这题不难,但是如果反过来想,可以避免很多高端算法,从后往前的思想确实不错。贴一个代码,有些冗长。

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<string>

 5 using namespace std;

 6 int ch[10005][20];

 7 int cnt;

 8 int n,m;

 9 char s[2000005];

10 int col[2000005];

11 bool dp[1000005];

12 void insert()

13 {

14     int now=0;

15     for(int i=strlen(s)-1;i>=0;i--)

16     {

17         int c=s[i]-'0';

18         if(!ch[now][c])

19         {

20             cnt++;

21             ch[now][c]=cnt;

22         }

23         now=ch[now][c];

24     }

25     col[now]=true;

26 }

27 bool cal(int x)

28 {

29     int deep=0;

30     int now=0;

31     for(int i=x;i>=1;i--)

32     {

33         int c=s[i]-'0';

34         if(ch[now][c]==0)return false;

35         now=ch[now][c];

36         deep++;

37         if(dp[x-deep] && col[now])return true;

38     }

39     return true;

40 }

41 void solve()

42 {

43     int ll=strlen(s+1);

44     for(int i=1;i<=ll;i++)

45     {

46         dp[i]=cal(i);

47     }

48     for(int i=ll;i>=0;i--)

49     {

50         if(dp[i])

51         {

52             printf("%d\n",i);

53             return;

54         }

55     }

56     return ;

57 }

58 int main()

59 {

60     scanf("%d%d",&n,&m);

61     for(int i=1;i<=n;i++)

62     {

63         scanf("%s",s);

64         insert();

65     }

66     for(int i=1;i<=m;i++)

67     {

68         memset(dp,0,sizeof(dp));

69         dp[0]=true;

70         scanf("%s",s+1);

71         solve();

72     }

73     return 0;

74 }
View Code

 

你可能感兴趣的:(AC自动机)