摘要: 就是POJ2778的加强版,思路是一样的。 出现过给定的单词的单词数=总单词数-未出现过给定单词的单词数,前者等于26^1+26^2+26^3....26^l,后者等于Mat^1+Mat^2+..Mat^l,这里的Mat是根据能走的字符之间的路径数建立出来的邻接矩阵。两者求出来一减就可以了,对2^64取模可以忽略,直接用unsigned long long做,忽视溢出就等于取模了,注意减法最后结果可能小于0,要加2^64变成正数。 求a^1+..a^n用一次二分就可以,建议这种二分都写成非递归的,效率比较高而且不会有爆栈的隐患。 #include <stdio.h>#include 阅读全文
posted @ 2012-08-07 10:04 Burn_E 阅读(242) 评论(0) 推荐(0)
摘要: 又是一道调了大半天的题,最后发现竟然是自己建立trie图的地方有个小BUG,这个小BUG在字符串匹配时没什么影响,所以一直没发现出来。刚刚学习,还是理解的不够深入啊。现在这个trie图应该算是写的很简洁了,可以拿来当模版了。 题意很简单,就是问长度为n不包含若干子串的串一共有多少个。这里可以用AC自动机DP,首先对于单词的结尾节点,标记为非法节点,一旦走到了一个非法节点,就说明包含了某个单词。网上的解题报告很多人说是AC自动机DP。但这题我的做法似乎没有用到DP,只是用矩阵加速了一下罢了。。。。首先标记出非法节点,补全trie图,用一个矩阵表示从每个合法节点到其它合法节点转移的方案,可... 阅读全文
posted @ 2012-08-06 15:50 Burn_E 阅读(282) 评论(0) 推荐(0)
摘要: 这道题好坑啊,整整调了我一下午!! 题意很简单,就是一个裸的自动机加上解码。编码是使用8位ASCII码连接字符,然后6位一取,结尾不足6位用0补上,每6位二进制数都会对应一个字符,形成了新的字符串。解码后最好用int存每一位的内容,写起来比较方便,因为可能会有'\0'这样的字符出现。。 一开始写了个位运算版本的解码,但是一直WA。于是写了个很暴力的模拟二进制解码,竟然A了,看来自动机部分没什么问题。然后又回过头来调我的位运算版解码,怎么算都没有错啊,但是就是一直WAWAWA。。。。最后绝望之中改了下数组大小,把字符串数组从2500改成了5000。。。然后,然后就神奇的A了。。跑 阅读全文
posted @ 2012-08-05 19:42 Burn_E 阅读(463) 评论(0) 推荐(0)
摘要: AC自动机的模版题,应该是很多人的AC自动机处女作吧。。 在斌牛的讲解下,总算是对AC自动机了解了个大概,这里采用了AC自动机和Trie图两种写法,据说后者在AC自动机DP中用的比较多,应该很快就会做到了。。。两者差不多,Trie图利用失败指针来建图,据说AC自动机到Trie图就是转化成了确定性有穷自动机。 贴一下两种写法的代码,当模版了。 AC自动机:#include <string.h>#include <stdio.h>#include <queue>#define MAXS 500010int cas,n;char s[55],find[100000 阅读全文
posted @ 2012-08-05 00:11 Burn_E 阅读(190) 评论(0) 推荐(0)
摘要: 感觉是不太好想的一道题,看完之后能想到是KMP,按照自己的想法敲了出来,但一直过不了。后来在网上搜题解搜到了一篇国家集训队的论文《由图论问题浅析算法优化》,论文中提到了这道题,想法很巧妙,类似于枚举,再加上KMP的优化。因为S较小(1~25),只要枚举模式串中的数字和匹配串中的数字的对应关系并且满足大小顺序关系就可以确定下来这个子串是否符合要求,具体的过程可以去看一下论文,这个算法的本质还是枚举,只是在枚举中进行了优化,并且使用KMP优化来快速找到符合对应关系的子串的位置,我的程序在POJ上跑了一秒多点,应该可以再优化。 但是上面的算法还是有缺点的,其复杂度是O(S*S*(N+M)),当... 阅读全文
posted @ 2012-08-05 00:00 Burn_E 阅读(913) 评论(0) 推荐(0)
摘要: 简单的KMP,考察对next数组的理解,next[i]表示S[1..i]中前缀和后缀的最大匹配程度。 假设字符串长度为L,用S[i..j]表示下标从i到j的字符组成的子串。 首先next[L]=x1,说明这个字符串S[1..x1]和S[L-x1+1..L]是相同的,所以x1是一个可能的公共前缀和后缀的长度值。然后next[x1]=x2,说明S[1..x2]和S[x1-x2+1..x1]是相等的,而S[1..x1]=S[L-x1+1..L],就有S[1..x2]=S[x1-x2+1..x1]=S[L-x2+1..L],所以x2也是一个可能的前缀和后缀的公共长度值,这样一直推到next[i... 阅读全文
posted @ 2012-08-03 13:08 Burn_E 阅读(180) 评论(0) 推荐(0)
摘要: 这题是在做KMP分类里做到的,网上搜到的题解也基本都是KMP解的。但这题根本不是KMP,在网上找了个KMP的程序,随便rand了10组数据,跑了10多秒。 题意比较纠结,就是说给你一个长度为N的串S,找出S[k..k+t-1]=s[N-t+1..N],其中1<=t<=13,k<=N-t,有多个k满足时,选择t最大的并且最靠右的,令S[N+1]=S[k+t],如果找不到符合条件的的K,则S[N+1]='0'。 正解应该是压缩状态,每个子串都由01组成,可以看作一个2进制数,因为t的范围<=13,所以用2^13就可以表示出所有的子串,用last[i][j]表 阅读全文
posted @ 2012-08-03 11:31 Burn_E 阅读(443) 评论(0) 推荐(0)
摘要: 一道KMP的好题,可惜数据实在是太弱了。 给出R*C的字符矩阵,问至少多大面积的小矩阵可以覆盖掉整个大矩阵。很容易想到的解法就是求出循环节然后求最大公倍数,但是这样就忽视了可以不用正好覆盖这个条件,比如aaabaa可以拆成aaab/aa,aaaba/a,aaabaa,而不一定非要拆成4的倍数。正确的做法是求出每一列可能拆分的长度,然后取所有列都可以分的长度中最小的。比如 abcdeaa aaabaaa 第一个串可以分的长度有5,7,第二个串可以分的长度有4,5,6,7,所以取5作为公共长度。至于怎么求一个字符串所有可以拆分的情况,用KMP处理一遍就可以了,然后从最后一列开始,取i=... 阅读全文
posted @ 2012-08-03 00:22 Burn_E 阅读(178) 评论(0) 推荐(0)
摘要: 考察对KMP的next数组的掌握,next数组也就是失败指针指向它失败后应该指向的位置,next[i]~i之间就是一个循环节,所以只要满足i%(i-next[i])==0即可。#include <string.h>#include <stdio.h>int cas=1,n;char s[1000005];int next[1000005];void solve(){ next[1]=0; int len=strlen(s+1); for(int i=2,j=0;i<=len;i++){ while(j>0&&s[i]!=s[j+1])j=ne 阅读全文
posted @ 2012-08-02 23:27 Burn_E 阅读(153) 评论(0) 推荐(0)
摘要: 给出一个字符串S1和S2,可以对S1进行添加字符(insert),删除字符(delete),替换字符(replace),交换相邻字符(swap)四种操作,问是否能在dis步骤内将S1转换成S2。 用d[i][j]表示将S1[1..i]转化为S2[1..j]的最小步数。 这几种操作可以表示为:添加d[i][j]=d[i][j-1]+1,删除d[i][j]=d[i-1][j]+1,替换d[i][j]=d[i-1][j-1]+1,交换d[i][j]=d[i-2][j-2]+1(条件为s1[i-1]==s2[j]&s1[i]==s2[j-1])。 但是仅考虑到这些还是过不了这道题的,因为交换. 阅读全文
posted @ 2012-08-02 14:35 Burn_E 阅读(443) 评论(0) 推荐(0)