【AC自动机+DP】匹配(match)
来源:互联网 发布:数据库的简单实现 编辑:程序博客网 时间:2024/06/06 02:16
匹配
【题目大意】给定k个字符串以及长度为n的母串的可选字母的集合,问母串要完整出现给定的k个字符串的方案数,答案模1000000007,字符仅包含小写字母。
(n<=100,m<=10,k<=8,给定字符串长度<=30)
【题解】本来这题是道较水的题,由于刚学了一种更快的建AC自动机的方法,就拿这个练练手。
对给定的k个字符串建立AC自动机。设f[i][j][k]为当前做到第i位(总共要N位),在自动机上的j节点,已经匹配了状态为k的字符串(k为二进制表示)的方案数。
f[i][j][k]可以转移到f[i+1][_j][_k],(_j = t[j].son[p],_k = k or t[_j].stat,p为枚举的下一个字符)。
若是j节点没有字符p这个儿子,则我们根据自动机的性质,就要在j节点的fail中(迭代)找到一个有字符p作为儿子的节点,并且要跳到那个节点上(这样可以保证匹配性)。这个操作在这种新的建ac自动机的方法中被完美解决。
以往代码:
void Construct_fail(){static int d[maxm];int l = 0, r = 1;while (l < r){int x = d[++l];fo(i,0,25)if (trie[x].son[i]){int v = trie[x].son[i];if (x == 0) trie[v].fail = 0;else{int p = trie[x].fail;while (p && !trie[p].son[i]) p = trie[p].fail;if (trie[p].son[i]) trie[v].fail = trie[p].son[i];else trie[v].fail = 0;}d[++r] = v;}}}
新方法:
void Construct_fail(){static int d[3*maxn];int l = 0, r = 1;while (l < r){int x = d[++l];fo(p,1,M){int i = a[p];if (t[x].son[i]){int v = t[x].son[i];if (x == 0) t[v].fail = 0;else t[v].fail = t[t[x].fail].son[i];t[v].stat |= t[t[v].fail].stat;d[++r] = v;} else t[x].son[i] = t[t[x].fail].son[i];}}}
(p循环是具体题目的要求)
可以发现新的构造方法省去了一个while循环,若节点x没有i这个儿子,我们直接将t[x].son[i] = t[t[x].fail].son[i];因为当我们匹配到x节点时,如果下一个字符是i,我们也会在x的fail中(迭代)找一个有i儿子的节点。因此直接赋值是正确的,而这个操作也让我们可以直接t[v].fail = t[t[x].fail].son[i](可以优化些许复杂度)。完整代码:
#include<cstdio>#include<cstring>#define fo(i,a,b) for (int i = a;i <= b;i ++)using namespace std;const int maxn = 105;const int P = 1000000007;int N,M,K,len,tot;int f[maxn][3*maxn][1<<8];int a[35],exist[35];char s[35];struct node{int son[26];int fail,stat;}t[3*maxn];void Insert(int x,int i,int id){int v = s[i] - 'a';if (!t[x].son[v]) t[x].son[v] = ++tot;if (i != len) Insert(t[x].son[v],i+1,id);else t[t[x].son[v]].stat = 1 << (id-1);}void Make_trie(){scanf("%d%d",&N,&K);fo(i,1,K){scanf("%s",s+1);len = strlen(s+1);Insert(0,1,i);}}void Construct_fail(){static int d[3*maxn];int l = 0, r = 1;while (l < r){int x = d[++l];fo(p,1,M){int i = a[p];if (t[x].son[i]){int v = t[x].son[i];if (x == 0) t[v].fail = 0;else t[v].fail = t[t[x].fail].son[i];t[v].stat |= t[t[v].fail].stat;d[++r] = v;} else t[x].son[i] = t[t[x].fail].son[i];}}}void Deal_matchstring(){int x;scanf("%d",&x);scanf("%s",s+1);fo(i,1,x)if (!exist[s[i]-'a']){exist[s[i]-'a'] = 1;a[++M] = s[i] - 'a';}}void DP(){f[0][0][0] = 1;fo(i,0,N-1)fo(j,0,tot)fo(k,0,(1<<K)-1)if (f[i][j][k])fo(p,1,M){int _j = t[j].son[a[p]];int _k = k | t[_j].stat;f[i+1][_j][_k] = (f[i+1][_j][_k] + f[i][j][k]) % P;}}void Print(){int ans = 0;fo(i,0,tot) ans = (ans + f[N][i][(1<<K)-1]) % P;printf("%d\n",ans);}int main(){freopen("match.in","r",stdin);freopen("match.out","w",stdout);Make_trie();Deal_matchstring();Construct_fail();DP();Print();return 0;}
0 0
- 【AC自动机+DP】匹配(match)
- [jzoj]3472. 【NOIP2013模拟联考8】匹配(match)(AC自动机+DP)
- UVA 11019 Matrix Matcher( 二维字符匹配 AC自动机 + DP)
- 字符串匹配-AC自动机
- AC自动机通配符匹配
- AC自动机通配符匹配
- AC自动机匹配
- 【AC自动机】地图匹配
- hdu4758 AC自动机+dp
- AC自动机 + DP小结
- AC自动机+DP+hdu2296
- hdu2457 AC自动机+DP
- hdu2296(AC自动机+DP)
- hdu2296 AC自动机+DP
- uvalive4842(AC自动机+DP)
- poj3691(ac自动机+dp)
- hdu3689(ac自动机+dp)
- poj3691(ac自动机+dp)
- 电容
- linux alsa pcm 播放声音
- 解决VS2010升级SP1后出现的warning C4005问题
- HTML5---Mozilla HTML5 Dashboard(HTML5新技术演示集合)
- 20140327收盘 忘了写了。。。当天没有操作。
- 【AC自动机+DP】匹配(match)
- VC中类型的相互转化
- cmake的簡單使用:
- oracle 创建、使用索引和判断索引是否被使用
- IBM在大数据时代的“新打法”
- 子串子序列相关面试题总结
- 计数排序
- Error: Table ad for model Ad was not found in datasource default.
- java&& Linux 线程大小