• kmp&字典树 模板


    kmp:

    const int maxn=1e5+5;
    char s[maxn],p[maxn];
    int nex[maxn];
    int KmpSearch(char* s, char* p)
    {
    	int i = 0;
    	int j = 0;
    	int sLen = strlen(s);
    	int pLen = strlen(p);
    	while (i < sLen && j < pLen)
    	{
    		//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++    
    		if (j == -1 || s[i] == p[j])
    		{
    			i++;
    			j++;
    		}
    		else
    		{
    			//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]    
    			//next[j]即为j所对应的next值      
    			j = nex[j];
    		}
    	}
    	if (j == pLen)
    		return i - j;
    	else
    		return -1;
    }
    void GetNext(char* p,int next[])
    {
    	int pLen = strlen(p);
    	nex[0] = -1;
    	int k = -1;
    	int j = 0;
    	while (j < pLen - 1)
    	{
    		//p[k]表示前缀,p[j]表示后缀
    		if (k == -1 || p[j] == p[k]) 
    		{
    			next[++j] = ++k;
    		}
    		else 
    		{
    			k = next[k];
    		}
    	}
    }
    //优化过后的next 数组求法
    void GetNextval(char* p, int next[])
    {
    	int pLen = strlen(p);
    	next[0] = -1;
    	int k = -1;
    	int j = 0;
    	while (j < pLen - 1)
    	{
    		//p[k]表示前缀,p[j]表示后缀  
    		if (k == -1 || p[j] == p[k])
    		{
    			++j;
    			++k;
    			//较之前next数组求法,改动在下面4行
    			if (p[j] != p[k])
    				next[j] = k;   //之前只有这一行
    			else
    				//因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] = next[next[k]]
    				next[j] = next[k];
    		}
    		else
    		{
    			k = next[k];
    		}
    	}
    }

      字典树:

    const int maxn=1e5+5;
    int trie[maxn][26];
    int sum[maxn];
    int exist[maxn];
    char s[maxn];
    int tot=0;
    void insert(char s[])  //插入字符串;
    {
        int len=strlen(s);
        int root=0;
        for(int i=0;i<len;i++)
        {   
            int id=s[i]-'a';
            if(trie[root][id]==0)
            {
                trie[root][id]=++tot; //tot新建节点编号;
                exist[root]=0;
            }
            root=trie[root][id];
            sum[root]++;   //表示有相同该前缀的单词个数;
        }
        exist[root]=1;   //该节点是存入的单词最后一位可以用来查询是否有这个单词;
    }
    // 查找是否为插入单词
    bool find(char s[])
    {
        int len=strlen(s);
        int root=0;
        for(int i=0;i<len;i++)
        {
            int id=s[i]-'a';
            if(trie[root][id]==0)  //不存在直接退出;
            {
                return false;
            }
            root=trie[root][id];
        }
        if(exist[root])
        {
            return true;
        }
        else return false;
    }
    // 查找前缀为 s出现的次数;
    int find_sum(char s[])
    {
        int len=strlen(s);
        int root=0;
        for(int i=0;i<len;i++)
        {
            int id=s[i]-'a';
            if(trie[root][id]==0)
            {
                return  0;
            }
            root=trie[root][id];
        }
        return sum[root];
    }
  • 相关阅读:
    如何正确夸奖孩子
    C# datatable分页和 list 分页
    js修改Switchery复选框的状态
    虚拟机中centos中设置固定IP
    CommonJS和ES6
    npm使用淘宝镜像
    RabbitMQ基础概念详细介绍
    Web漏洞扫描神器Nikto使用指南
    Redis基本使用
    ROS文件系统导览
  • 原文地址:https://www.cnblogs.com/zpj61/p/13435925.html
Copyright © 2020-2023  润新知