zoukankan      html  css  js  c++  java
  • 【挑战程序设计竞赛】后缀数组 实现字符串匹配

    字符串后缀Suffix 指的是从字符串的某个位置开始到其末尾的字符串字串

    后缀数组 Suffix Array 指的是将某个字符串的所有后缀按字典序排序之后得到的数组,不过数组中不直接保存所有

    的后缀子串,只要记录相应的位置就好了。

    下面的代码使用倍增法来构造后缀数组,该算法的复杂度是 O(n log n)常数因子比较大。

    基于后缀数组的字符串匹配,我们可以通过二分搜索来完成,算法复杂度是 O(|T|log|S|) 其中 S 是主串,T是模式串

    具体的后缀数组的原理可以详细去看看国家队集训的论文,罗穗骞《后缀数组——处理字符串的有力工具》:

    #include <iostream>
    #include <cstring>
    #include <cstddef>
    #include <cstdio>
    #include <string>
    #include <algorithm> 
    
    using namespace std;
    const int MAXN = 10001;
    int n,k;
    int rank[MAXN+1],tmp[MAXN+1];
    
    bool comp_sa(int i, int j)
    {
    	if(rank[i] != rank[j]) 
    		return rank[i] < rank[j];
    	int ri = i+k <= n? rank[i+k] : -1;
    	int rj = j+k <= n? rank[j+k] : -1;
    	return ri < rj; 
    }
    
    void calc_sa(string &S, int *sa) //计算字符串S的后缀数组 
    {
    	n = S.size();
    	
    	//初始长度为1 
    	for(int i = 0; i <= n; i++)
    	{
    		sa[i] = i;
    		rank[i] = i < n ? S[i] : -1;
    	}
    	
    	for( k =1; k <= n; k *= 2)
    	{
    		sort(sa,sa+n+1,comp_sa);
    		
    		//先在tmp中临时存储新计算的rank,再转存回rank中 
    		tmp[sa[0]] = 0;
    		for(int i = 1; i <= n; i++)
    		{
    			tmp[sa[i]] = tmp[sa[i-1]] + (comp_sa(sa[i-1],sa[i]) ? 1: 0);
    		}
    		for(int i = 0; i <= n; i++)
    		{
    			rank[i] = tmp[i];
    		}
    	}
    }
    
    void SuffixArrayMatch(string &S, int *sa, string T)
    {
    	calc_sa(S,sa);
    	int lhs = 0, rhs = S.size();
    	
    	//使用二分查找 
    	while(rhs - lhs > 1)
    	{
    		int mid = (lhs + rhs)>>1;
    		int res = S.compare(sa[mid],T.size(),T); 
    		if(res < 0)
    			lhs = mid;
    		else if(res == 0) 
    		{
    			cout<<"match at: "<<sa[mid]<<endl;
    			lhs = mid;
    		}
    		else rhs = mid;
    	}
    }
    int main()
    {
    	string S = "abracadabra";
    	string T = "ab";
    	int *sa = new int[S.size()+1];
     	SuffixArrayMatch(S,sa,T);
     	delete [] sa;
     	sa = NULL;
    }


  • 相关阅读:
    http数据返回值
    刷新 返回
    微信平台上遇到的bug
    iscroll修改
    iscroll
    a标签的herf和click事件
    ios9+xcode7 适配笔记
    xsd、wsdl生成C#类的命令行工具使用方法
    xcode更新,想想也是醉了
    关于#define预处理指令的一个问题
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3356097.html
Copyright © 2011-2022 走看看