有n個串,代表n個人的姓氏和名字,都是用很多個數字表示的,比如我姓1,2,3,4,名4,5,6,7。然後有m個點名串,如果點到了某個人的姓或名裡面的某一串,那個人就被點到,不過乙個人在乙個點名串中只能被點一次。比如點名串是2,3,4,我的姓中含有2,3,4,那麼我就會被叫到。求每個學生分別被叫到多少次,和每個點名串分別叫到多少個學生。
這一題,很明顯是用乙個個的姓氏和名字在點名樹中匹配,那麼用到的演算法明顯是ac_automation(ac自動機)。那麼為什麼不是用乙個個點名串在姓名樹中匹配呢——>因為如果這樣做,那麼就有一顆姓樹和一顆名樹,明顯比建造點名樹要麻煩的多。然後套了ac自動機的模板,還要考慮一件事(這個坑了我好久,我還以為沒有重複串),點名串可能有重複串(不用管姓名串了,因為我們是逐個匹配),如果有重複的姓名串,那麼還要用乙個陣列存此節點含有那些點名串,然後統計答案。
#include
#include
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using
namespace
std;
char s[10005];
bool bz[100005],cz[100005];
map trie[100005];
int i,j,k,l,t,n,m,tot,x,num,da;
vector
a[1000005],b,c,d[100005],biao[1000005];
int data[1000005],ans[1000005],ans1[1000005],next[1000005],sum[1000005];
void build_ac_automation(int root)
if(now==1) next[x]=1;
data[++tail]=x;}}
}int main()
a[i].push_back(-1);
scanf("%d",&l);
fo(j,1,l)
}num=1;
fo(i,1,m)
else x=trie[x][t];
}biao[x].push_back(i);
}build_ac_automation(1);
fo(l,1,n)}}
}for(i=0;i0;
c.clear();b.clear();
}fo(i,1,m) printf("%d\n",ans[i]);
fo(i,1,n) printf("%d ",ans1[i]);
}}
SCOI2012 喵星球上的點名
給出n個模式串,m個文字串,每個模式串由兩部分組成,我們認為乙個模式串被乙個文字串包含只要這個文字串包含它的兩部分中的其中一部分的子串。求每個文字串包含多少個模式串,每個模式串又被多少個文字串包含。1 n 20000,1 m 50000,模式串總長和文字串的總長分別不超過100000 保證模式串和文...
SCOI2012 喵星球上的點名
對於第乙個詢問,對於姓名串建廣義字尾自動機,那麼我們對於插入乙隻喵的姓名串,要將這兩個 姓和名 串的所有字串位置打標記,怎麼搞呢,其實可以直接插入暴力向上跳,複雜度的話 對於乙個串假設長度為x,那麼插入複雜度是min x x,x n 而最多只有n x個這樣的串,算一下總的複雜度上界是n根號的。然後就...
SCOI2012 喵星球上的點名
點此看題 0x01 ac自動機 如果字符集沒有這麼大的話,就是ac text ac自動機的板題。我們可以開map mapma p存轉移,然後就完了。寫了之後對map mapma p的理解會有所提公升吧,雖然是過不了luo gu luogu luog u的加強版,還是貼個 include includ...