KMP
KMP的关键是求出next的值、先预处理出next的值、然后一遍扫过、复杂度O(m+n)
http://acm.hdu.edu.cn/showproblem.php?pid=1711
#include<bits/stdc++.h>
using namespace std;
const int N=1000000+7;
const int M=10000+7;
int n,m;
int a[N],b[M],Next[M];
int kmp()
{
int i=0,j,k=-1;
Next[0]=-1;
while(i<m)
{
if(k==-1||b[i]==b[k]) Next[++i]=++k;
else k=Next[k];
}
i=0,j=0;
while(i<n)
if(a[i]==b[j])
{
if(j==m-1) return i-j+1;
i++,j++;
}
else
{
j=Next[j];
if(j==-1) i++,j=0;
}
return -1;
}
int main()
{
int i,j,t,tt=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(i=0;i<n;i++) scanf("%d",&a[i]);
for(i=0;i<m;i++) scanf("%d",&b[i]);
if(n<m) {printf("-1\n");continue;}
printf("%d\n",kmp());
}
return 0;
}
Map
map的详细用法 http://blog.csdn.net/sunshinewave/article/details/8067862/
http://acm.hdu.edu.cn/showproblem.php?pid=1880
不Hash超内存,所以使用Map的时候一定要计算好时间和空间
#include<bits/stdc++.h>
using namespace std;
const int N=50000+7;
const int mod=1000000007;
map<string,string> mp1,mp2;
int main()
{
int i,j,t,tt=0;
string s;
while(getline(cin,s))
{
if(s=="@END@") break;
int tmp=s.find(']');
string from=s.substr(1,tmp-1);
string to=s.substr(tmp+2,s.size()-1);
mp1[from]=to;
mp2[to]=from;
}
int n;
scanf("%d",&n);getchar();
while(n--)
{
getline(cin,s);
if(s[0]=='[')
{
s=s.substr(1,s.size()-2);
if(mp1.find(s)!=mp1.end()) cout<<mp1[s]<<endl;
else printf("what?\n");
}
else
{
if(mp2.find(s)!=mp2.end()) cout<<mp2[s]<<endl;
else printf("what?\n");
}
}
}
Hash
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
using namespace std;
#define debug cout<<"***"<<endl;
map <int,int> m1,m2;
const int maxn=105000;
char spell[maxn][100];
char magic[maxn][100];
int f1[maxn];
int f2[maxn];
int pos1=1,pos2=1;
unsigned int BKDRHash(char *str)
{
unsigned int seed = 131;
unsigned int hash = 0;
while (*str){
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
void init(){
for(int i=1;i<pos1;i++){
m1[BKDRHash(magic[i])]=i;
m2[BKDRHash(spell[i])]=i;
//f1[BKDRHash(magic[i])]=i;debug;
//f2[BKDRHash(spell[i])]=i;
}
}
int main(){
memset(f1,-1,sizeof(f1));
memset(f2,-1,sizeof(f2));
while(scanf("%s",magic[pos1])){
if(!strcmp(magic[pos1],"@END@"))
break;
getchar();
gets(spell[pos2]);
pos1++;
pos2++;
}
init();
int t;
scanf("%d",&t);
getchar();
while(t--){
char str[100];
gets(str);
if(str[0]=='['){
int tmp=m1[BKDRHash(str)];
if(tmp==0)
printf("what?\n");
else
printf("%s\n",spell[tmp]);
}
else{
int tmp=m2[BKDRHash(str)];
if(tmp==0)
printf("what?\n");
else
for(int i=1;i<strlen(magic[tmp])-1;++i)
printf("%c",magic[tmp][i]);
printf("\n");
}
}
return 0;
}
Tire
Trie树用途例子:如何求字符串的所有不同子串
可以看出将n个模式串插入到一棵单词前缀树的时间复杂度为 O(∑len(i)) ,其中len(i)为第i个模式串的长度。
C++才能过:http://acm.hdu.edu.cn/showproblem.php?pid=1251
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int N=505;
const int inf=0x3f3f3f3f;
struct node{
int total;
node *next[30];
node(){
memset(next,0,sizeof(next));
total=0;
}
};
node *p,*root=new node();
void Insert(char s[]){
p=root;
for(int i=0;s[i];i++)
{
int x=s[i]-'a';
if(p->next[x]==NULL) p->next[x]=new node;
p=p->next[x];
p->total++;
}
}
int Search(char s[]){
p=root;
for(int i=0;s[i];i++){
int x=s[i]-'a';
if(p->next[x]==NULL) return 0;
p=p->next[x];
}
return p->total;
}
//void Delete(int cnt){
// p=root;
// for(int i=0;s[i];i++)
// {
// int x=s[i]-'a';
// p=p->next[x];
// p->total-=cnt;
// }
// for(int i=0;i<30;i++) p->next[i]=0;
//}
// int cnt=Search();
// if(cnt) Delete(cnt);
int main()
{
char s[33];
while(gets(s),*s) Insert(s); //一直读入数据,直到遇到空字符串
while(gets(s)) printf("%d\n",Search(s));
return 0;
}
trie图是一种DFA,可以由trie树为基础构造出来,
对于插入的每个模式串,其插入过程中使用的最后一 个节点都作为DFA的一个终止节点。
如果要求一个母串包含哪些模式串,以用母串作为 DFA的输入,在DFA 上行走,走到终止节点,就意 味着匹配了相应的模式串(没能走到终止节点,并不 意味着一定不包含模式串)。
BZOJ2938 POI2000 病毒 题解&代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 30005;
int n, tot, ch[maxn][2], fail[maxn], danger[maxn], q[maxn], flag, temp, vis[maxn], e[maxn];
char s[maxn];
void addtrie(char s[])
{
int x = 0, p = 0, len = strlen(s);
while( p < len )
{
temp = s[p]-'0';
if( !ch[x][temp] ) ch[x][temp]=++tot;
x = ch[x][temp];
p++;
}
danger[x] = 1;
}
void AC(void)
{
int h = 0, t = 0;
for(int i = 0; i < 2; i++)
if(ch[0][i]) q[t++] = ch[0][i];
while( h < t )
{
temp = q[h++];
for(int i = 0; i < 2; i++)
{
if(!ch[temp][i]) ch[temp][i] = ch[fail[temp]][i];
else
{
fail[ch[temp][i]] = ch[fail[temp]][i];
danger[ch[temp][i]] |= danger[ch[fail[temp]][i]];
q[t++] = ch[temp][i];
}
}
}
}
void dfs(int x)
{
if(flag) return;
if(x) vis[x] = 1;
for(int i = 0; i < 2; i++)
{
int v = ch[x][i];
if(vis[v])
{
flag = 1;
return;
}
if(e[v] || danger[v])continue;
e[v] = 1;
dfs(v);
}
vis[x] = 0;
}
int main(void)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%s", s);
addtrie(s);
}
AC();
dfs(0);
if(flag) printf("TAK\n");
else printf("NIE\n");
return 0;
}
例题: POJ2778 DNA Sequence