bzoj 1212 [HNOI2004] L语言(不用AC自动机)
2015-07-12 16:01
465 查看
网上的题解大多树都要建一棵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,轻松过。
这题不难,但是如果反过来想,可以避免很多高端算法,从后往前的思想确实不错。贴一个代码,有些冗长。
View Code
首先,我们可以轻松列出状态转移方程 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,轻松过。
这题不难,但是如果反过来想,可以避免很多高端算法,从后往前的思想确实不错。贴一个代码,有些冗长。
#include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; int ch[10005][20]; int cnt; int n,m; char s[2000005]; int col[2000005]; bool dp[1000005]; void insert() { int now=0; for(int i=strlen(s)-1;i>=0;i--) { int c=s[i]-'0'; if(!ch[now][c]) { cnt++; ch[now][c]=cnt; } now=ch[now][c]; } col[now]=true; } bool cal(int x) { int deep=0; int now=0; for(int i=x;i>=1;i--) { int c=s[i]-'0'; if(ch[now][c]==0)return false; now=ch[now][c]; deep++; if(dp[x-deep] && col[now])return true; } return true; } void solve() { int ll=strlen(s+1); for(int i=1;i<=ll;i++) { dp[i]=cal(i); } for(int i=ll;i>=0;i--) { if(dp[i]) { printf("%d\n",i); return; } } return ; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%s",s); insert(); } for(int i=1;i<=m;i++) { memset(dp,0,sizeof(dp)); dp[0]=true; scanf("%s",s+1); solve(); } return 0; }
View Code
相关文章推荐
- [Guava] EventBus
- Lowest Common Ancestor of a Binary Search Tree
- java中的线程创建和使用
- Myeclipse快捷键
- Java多线程笔记
- win7下搭建opengl es 2.0开发环境
- 处理动态链表所需函数
- MyEclipse中更换JDK及工程警告问题
- 高效的动态语言开发环境(python: linux + emacs + evil + *.el)
- Python下opencv使用笔记(六)(图像的形态学转换)
- thinkphp模型没继承model报的错
- 乱弹纪录I:Geometry Shader
- 最小二乘法&梯度下降法
- mongoVue的使用
- Jquery_选择器
- Jquery-Ajax
- Climbing Stairs
- 有序数组中找中位数
- MongoDB的nodejs 键值压缩driver
- 剑指offer《面试题5:从尾到头打印链表》