ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

模板整理

2022-01-29 01:32:23  阅读:96  来源: 互联网

标签:rt int next char 整理 include 模板


KMP模板:

 

KMP模板1:简单的字符串匹配


//KMP模板1,简单的字符串匹配

void GetNextVal(int* p) //得next数组;next[i]是下标为i的字符之前后缀和前缀相同的最长长度
{
    next[0]=-1;
    int k=-1,j=0;
    while(j<m-1)
    {
        if(k==-1||p[j]==p[k])
        {
            if(p[++j]==p[++k])  //当两个字符相等时要跳过(优化)
                next[j]=next[k];
            else
                next[j]=k;
        }
       else { k=next[k]; } } } int KmpSearch(int* s,int* p) //在主串中查找子串出现的位置 { int i=0,j=0; //i是主串的位置,j是模式串的位置 while(i<n&&j<m) { if(j==-1||s[i]==p[j]) // j为-1,主串后移一位;当两个字符相同,就比较下一个 { ++i; ++j; } else { j=next[j]; //只移动模式串,回到指定位置 } } if(j==m) return i-j; //如果找到,返回在主串中第一个字符出现的下标,否则为-1

  else return -1;
}

 

KMP模板2:求模式串在待匹配串中的出现次数(不重复)

 

//KMP模板2,求模式串在待匹配串中的出现次数(不重复)
void GetNextVal(char* p)
{
    next[0]=-1;
    int k=-1,j=0;
    while(j<m-1)//m为模式串长度
    {
        if(k==-1||p[j]==p[k])
        {
            if(p[++j]==p[++k])
                next[j]=next[k];
            else
                next[j]=k;
        }
        else
        {
            k=next[k];
        }
    }
}
int KmpSearch(char* s,char* p)
{
    int i=0,j=0,cnt=0;
    while(i<n)//n为主串长度
    {
        if(j==-1||s[i]==p[j])
        {
            ++i;
            ++j;
        }
        else
        {
            j=next[j];
        }
        if(j==m)//m为模式串长度
        {
            cnt++;
            j=0;//找到之后模式串回到最开头位置
        }
    }
    return cnt;//返回出现次数
}

 

 

 

KMP模板3:求模式串在待匹配串中的出现次数(可重复)

//KMP模板3,求模式串在待匹配串中的出现次数(可重复)
void GetNextVal(char* p)
{
    next[0]=-1;
    int k=-1,j=0;
    while(j<m) //m为模式串长度
    {
        if(k==-1||p[j]==p[k]) //这里不要优化
        {
            next[++j]=++k;
        }
        else
        {
            k=next[k];
        }
    }
}
int KmpSearch(char* s,char* p)
{
    int i=0,j=0,cnt=0;
    while(i<n)//n为主串长度
    {
        if(j==-1||s[i]==p[j])
        {
            ++i;
            ++j;
        }
        else
        {
            j=next[j];
        }
        if(j==m)//m为模式串长度
        {
            cnt++;
            j=next[j];//找到之后模式串回到指定位置
        }
    }
    return cnt;//返回出现次数
}

 

字符串循环节长度为 :len - next[len] ;(len为字符串长度)//跑一个next数组即可

 

字典树模板: 插入和查找

//字典树模板(插入和查找)
void insert()//插入单词s
{
    len=strlen(s);//单词s的长度
    root=0;//根节点编号为0
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'a';//第二种编号
        if(!trie[root][id])//如果之前没有从root到id的前缀 
                    trie[root][id]=++tot;//插入,tot即为第一种编号
        root=trie[root][id];//顺着字典树往下走
    }
}

bool find() //查找单词s
{
    len=strlen(s);
    root=0;//从根结点开始找
    for(int i=0;s[i];i++)
    {
        int x=s[i]-'a';//
        if(trie[root][x]==0)   return false;//以root为头结点的x字母不存在,返回0 
        root=trie[root][x];//为查询下个字母做准备,往下走 
    }
    return true;//找到了
}

 

 字典树完整模板1:查询前缀(或整个单词)是否出现

//字典树完整模板1,查询是否出现(前缀或整个单词)
/*
  trie tree的储存方式:将字母储存在边上,边的节点连接与它相连的字母 
  trie[rt][x]=tot:rt是上个节点编号,x是字母,tot是下个节点编号 
*/ 
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 2000010
using namespace std;
int tot=1,n;
int trie[maxn][26];
//bool isw[maxn];查询整个单词用
void insert(char *s,int rt)
{
    for(int i=0;s[i];i++)
    {
        int x=s[i]-'a';
        if(trie[rt][x]==0)//现在插入的字母在之前同一节点处未出现过 
        {
            trie[rt][x]=++tot;//字母插入一个新的位置,否则不做处理 
        }
        rt=trie[rt][x];//为下个字母的插入做准备  
    }
    /*isw[rt]=true;标志该单词末位字母的尾结点,在查询整个单词时用到*/
}
bool find(char *s,int rt)
{
    for(int i=0;s[i];i++)
    {
        int x=s[i]-'a';
        if(trie[rt][x]==0)return false;//以rt为头结点的x字母不存在,返回0 
        rt=trie[rt][x];//为查询下个字母做准备 
    }
    return true;
    //查询整个单词时,应该return isw[rt] 
}
char s[22];
int main()
{
    tot=0;
    int rt=1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        insert(s,rt);
    }
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        if(find(s,rt))printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

 

字典树完整模板2:查询前缀出现次数

//字典树完整模板2,查询前缀出现次数
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int trie[400001][26],len,root,tot,sum[400001];
bool p;
int n,m; 
char s[11];
void insert()
{
    len=strlen(s);
    root=0;
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'a';
        if(!trie[root][id]) trie[root][id]=++tot;
        sum[trie[root][id]]++;//前缀后移一个位置保存 
        root=trie[root][id];
    }
}
int search()
{
    root=0;
    len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'a';
        if(!trie[root][id]) return 0;
        root=trie[root][id];
    }//root经过此循环后变成前缀最后一个字母所在位置的后一个位置 
    return sum[root];//因为前缀后移了一个保存,所以此时的sum[root]就是要求的前缀出现的次数 
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        insert();
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        cin>>s;
        printf("%d\n",search());
    }
}

 

字典树模板指针写法:

//字典树模板指针写法
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char s[11];
int n,m;
bool p;
struct node
{
    int count;
    node * next[26];
}*root;
node * build()
{
    node * k=new(node);
    k->count=0;
    memset(k->next,0,sizeof(k->next));
    return k;
}
void insert()
{
    node * r=root;
    char * word=s;
     while(*word)
    {
        int id=*word-'a';
        if(r->next[id]==NULL) r->next[id]=build();
        r=r->next[id];
        r->count++;
        word++;
    }
}
int search()
{
    node * r=root;
    char * word=s;
    while(*word)
    {
        int id=*word-'a';
        r=r->next[id];
        if(r==NULL) return 0;
        word++;
    }
    return r->count;
}
int main()
{
    root=build();
    scanf("%d",&n);
    for(int i=1;i<=n;i++) 
    {
            cin>>s;
            insert();
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        cin>>s;
        printf("%d\n",search());
    }
}

 

 manacher模板:求字符串中最长回文串长度

 

//manacher模板,求字符串中最长回文串长度
const int maxn=1000010;
char MA[maxn<<1];
int MP[maxn<<1];
void Manacher(char s[],int len)
{
    int l=0;
    MA[l++]='$';
    MA[l++]='#';
    for(int i=0;i<len;i++)
    {
        MA[l++]=s[i];
        MA[l++]='#';
    }
    MA[l]=0;
    int mx=0,id=0;
    for(int i=0;i<l;i++)
    {
        MP[i]=mx>i?min(MP[2*id-i],mx-i):1;
        while(MA[i+MP[i]]==MA[i-MP[i]])
            MP[i]++;
        if(i+MP[i]>mx)
        {
            mx=i+MP[i];
            id=i;
        }
    }
}
char s[maxn];
 
int main()
{
    while(scanf("%s",s)!=EOF)
    {
        int len=strlen(s);
        Manacher(s,len);
        int ans=0;
        for(int i=0;i<2*len+2;i++)
            ans=max(ans,MP[i]-1);
        printf("%d\n",ans);
    }
    return 0;
}

 

标签:rt,int,next,char,整理,include,模板
来源: https://www.cnblogs.com/Angel55/p/9532037.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有