首页 > 其他分享 >luogu P3808/3796

luogu P3808/3796

时间:2024-09-05 20:02:56浏览次数:3  
标签:2000005 int luogu 3796 son char P3808 ans using

首先
Trie树:

#include<bits/stdc++.h>
using namespace std;
int T,q,n,t[3000005][65],cnt[3000005],idx;
char s[3000005];
int getnum(char x){
    if(x>='A'&&x<='Z')
        return x-'A';
    else if(x>='a'&&x<='z')
        return x-'a'+26;
    else
        return x-'0'+52;
} 
void insert(char str[]){
    int p=0,len=strlen(str);
    for(int i=0;i<len;i++){
        int c=getnum(str[i]);
        if(!t[p][c])
            t[p][c]=++idx;
        p=t[p][c];
        cnt[p]++;
    }
}
int find(char str[]){
    int p=0,len=strlen(str);
    for(int i=0;i<len;i++){
        int c=getnum(str[i]);
        if(!t[p][c])
            return 0;
        p=t[p][c];
    }
    return cnt[p];
}
int main(){
    scanf("%d",&T);
    while(T--){
        for(int i=0;i<=idx;i++)
            for(int j=0;j<=122;j++)
                t[i][j]=0;
        for(int i=0;i<=idx;i++)
            cnt[i]=0;
        idx=0;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            insert(s);
        }
        for(int i=1;i<=q;i++){
            scanf("%s",s);
            printf("%d\n",find(s));
        }
    }
    return 0;
}

烤馍片kmp:

#include<bits/stdc++.h>
using namespace std;
int kmp[1000010];
int la,lb,j;
char a[1000010],b[1000010];
int main() {
	cin>>a+1;
	cin>>b+1;
	la=strlen(a+1);
	lb=strlen(b+1);
	for (int i=2; i<=lb; i++) {
		while(j&&b[i]!=b[j+1])j=kmp[j];
		if(b[j+1]==b[i])j++;
		kmp[i]=j;
	}
	j=0;
	for(int i=1; i<=la; i++) {
		while(j>0&&b[j+1]!=a[i])j=kmp[j];
		if (b[j+1]==a[i])j++;
		if (j==lb) {
			cout<<i-lb+1<<endl;
			j=kmp[j];
		}
	}
	for (int i=1; i<=lb; i++)cout<<kmp[i]<<" ";
	return 0;
}

易得:

#include<bits/stdc++.h>
using namespace std;
char s[2000005],T[2000005];
int n,cnt,vis[200051],ans,in[2000005],Map[2000005];
struct jntm{
    int son[26],fail,flag,ans;
    void clear(){memset(son,0,sizeof(son)),fail=flag=ans=0;}
}trie[2000005];
queue<int>q;
void insert(char* s,int num){
    int u=1,len=strlen(s);
    for(int i=0;i<len;i++){
        int v=s[i]-'a';
        if(!trie[u].son[v])trie[u].son[v]=++cnt;
        u=trie[u].son[v];
    }
    if(!trie[u].flag)trie[u].flag=num;
    Map[num]=trie[u].flag;
}
void getFail(){
    for(int i=0;i<26;i++)trie[0].son[i]=1;
    q.push(1);
    while(!q.empty()){
        int u=q.front();q.pop();
        int Fail=trie[u].fail;
        for(int i=0;i<26;i++){
            int v=trie[u].son[i];
            if(!v){trie[u].son[i]=trie[Fail].son[i];continue;}
            trie[v].fail=trie[Fail].son[i]; in[trie[v].fail]++;
            q.push(v);
        }
    }
}
void topu(){
    for(int i=1;i<=cnt;i++)
    if(in[i]==0)q.push(i);
    while(!q.empty()){
        int u=q.front();q.pop();vis[trie[u].flag]=trie[u].ans;
        int v=trie[u].fail;in[v]--;
        trie[v].ans+=trie[u].ans;
        if(in[v]==0)q.push(v);
    }
}
void query(char* s){
    int u=1,len=strlen(s);
    for(int i=0;i<len;i++)
    u=trie[u].son[s[i]-'a'],trie[u].ans++;
}
int main(){
    scanf("%d",&n); cnt=1;
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        insert(s,i);
    }getFail();scanf("%s",T);
    query(T);topu();
    for(int i=1;i<=n;i++)printf("%d\n",vis[Map[i]]);
}

标签:2000005,int,luogu,3796,son,char,P3808,ans,using
From: https://www.cnblogs.com/zan-mei-tai-yang/p/18399167

相关文章

  • [luoguP4051/JSOI2007] 字符加密
    题意给定字符串\(s\),输出将\(s\)的所有循环同构的字符串排序后,每个字符串的末尾的字符。sol因为要对循环同构的字符串排序,因此我们可以将\(s\)复制一遍,拼在后面,计算\(sa\),满足\(sa_i\len\)的所有元素的相对位置即为排序后字符串的相对位置,输出即可\(sa\)的计算详见......
  • [luoguP3809]后缀排序
    题意给定一个字符串,要求将它的所有后缀按照字典序排序,并按顺序输出每个后缀第一个字符的下标。sol这是后缀数组(SuffixArray,SA)的板子题。我们定义:\(s_{i\cdotsj}\)表示\(s\)中下标在\(i\)到\(j\)之间的子串。\(sa_i\)表示排名为\(i\)的后缀第一个字符的下标;\(......
  • Luogu P10997 Partition 题解 [ 蓝 ] [ 轮廓 dp ]
    Partition:一道dp神题,用到了以轮廓线的轨迹来做dp的技巧,和敲砖块这题的状态设计有点相似。观察首先观察样例,发现整张图可以看作是被两条线分隔开的。同时每个颜色的四个方向上又存在一大堆奇怪的性质,很容易发现这两条线一条是从左上到右下的线,另一条是从右下到左上的线。暴......
  • luoguP5369 [PKUSC2018] 最大前缀和
    题目n<=20题解想了半天3位状态的折半,然后发现空间开不下(时间也不太行)所以放弃思考,直接枚举答案答案是a中的一个集合,设为S;记集合S的和为sum[S]考虑当S确定时,有多少种方案能使答案恰好为sum[S]。为了处理多种sum相同的情况,记S为从前往后考虑,第一次出现最大ans的集合;记剩余部......
  • luoguP4907 A换B problem
    数据有点水,加个卡时就可以过。代码加注释送上:#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<ctime>#defineLLlonglongusingnamespacestd;LLread(){ LLk=0,f=1;charc=getchar(); while(c<......
  • Luogu P4425 转盘 题解 [ 黑 ] [ 线段树 ] [ 贪心 ] [ 递归 ]
    转盘:蒟蒻的第一道黑,这题是贪心和线段树递归合并的综合题。贪心破环成链的trick自然不用多说。首先观察题目,很容易发现一个性质:只走一圈的方案一定最优。这个很容易证,因为再绕一圈回来标记前面的和等前面的标记完之后继续走是等价的,并且再绕一圈甚至可能更劣。于是,我们只用走......
  • Luogu P4588 数学运算 题解 [ 绿 ] [ 线段树 ]
    LuoguP4588数学运算。虽然是一个很典的题,但里面的思想还是比较值得记录的。假做法一开始看到此题还以为是乘法逆元的模板题,但看到\(m\)与\(M\)不互质,就知道这种做法是假的了。注意exgcd虽然能求模数为合数的逆元,但是要是两数不互质就什么算法都搞不了了。因此,本题不能......
  • Luogu P7250 BalticOI 山峰 题解 [ 蓝 ] [ 模拟 ] [ 并查集 ] [ BFS ]
    LuoguP7250BalticOI山峰。一道大模拟,很暴力,也很难写。建议紫或蓝,标签为模拟、广度优先搜索、并查集。思路首先观察到答案取决于路线上的最低点,所以我们可以把所有点的高度丢进一个桶里,从大到小枚举,尝试更新答案。这应该是个挺经典的trick了。感性理解可以看作所有山都先......
  • Solution - Luogu P10918 小分图最大匹配
    首先考虑连边的情况。可以把\(a_i\)拆成\(\gcd(a_i,m)\times\frac{a_i}{\gcd(a_i,m)}\),因为\(\gcd(\frac{a_i}{\gcd(a_i,m)},m)=1\),所以与\(a_i\)有连边的\(j\)一定满足\(j\bmod\gcd(a_i,m)=0\)。于是就可以把\(c_{a_i}\)放到\(c_{\gcd(a_i,m)}\),左部点......
  • [lnsyoj2286/luoguP4458/BJOI2018]链上二次求和
    题意给定序列\(a\),要求支持修改与查询操作:修改操作为对区间\(l,r\)的每个数\(+d\),查询操作为给定区间\(l,r\),要求查询:\[\sum_{len=l}^r\sum_{i=l}^{n-len+1}\sum_{j=l}^{i+len-1}a_j\]sol化简式子(下设\(sum_i=\sum_{j=1}^ia_j,ssum_i=\sum_{j=1}^isum_j\)):\[\begin{al......