找到数组中的第一个字符串匹配

时间:2016-03-10 06:53:41

标签: string algorithm search

我写了一个简单的字符串搜索算法,我想改进,我应该从哪里开始?

我想要更改简单算法的原因是:

  1. pool似乎是一个很大的数组
  2. toSearch中的字符串似乎是长字符串
  3. 以下是代码:

    var pool []string = []string{"st", "se", "go", "es", "per", "123", "abcd", "e", "2"}
    
    func search(aStr string) (index int) {
        for i, s := range pool {
            if strings.Contains(aStr, s) {
                return i
            }
        }
    
        return -1
    }
    
    func main() {
        toSearch := []string{"string", "search", "algorithm", "best", "performance"}
        for _, s := range toSearch {
            idx := search(s)
            fmt.Printf("search %s in %d(%s)\n", s, idx, pool[idx])
        }
    }
    

1 个答案:

答案 0 :(得分:2)

您可以使用特殊字符加入toSearch数组中的所有字符串,例如$,然后您的搜索字符串将变为"string$search$algorithm$best$performance",您也可能需要分配一个数组,如果找到匹配项,将记录您当前所在的字符串。

我担心池数组你必须逐个搜索上面创建的字符串。

降低复杂性的方法之一是对池数组的每个元素使用线性时间模式匹配算法,而不是使用的二次时间模式匹配算法。

我发布了3个线性时间算法来搜索给定字符串中的模式,其中2个是确定性的,最后一个是非确定性的。

确定性和更标准的解决方案之一是使用Knuth Morris Pratt algorithm,虽然理解您可以轻松找到在线实现它的代码有点复杂。它是线性时间,其中m是输入字符串的长度,n是模式的长度。

另一个确定性算法和我最喜欢的算法之一是Z算法 更容易理解和实现,也是线性时间,它构造了所谓的Z数组,即用于轻松计算字符串中的模式匹配。您可以在Z Algorithm

上查看此链接

如果你想使用非确定性算法,你可以使用Rabin Karp algorithm,它需要散列(特别是Rolling Hash的概念),它是最容易实现的并且是线性时间。如果你检查使用哈希得到的字符串是否正确,也可以确定是否由于冲突,但在最坏的情况下,如果你使rabin karp算法确定性,它会给出二次复杂度。

我使用下面的Z算法编写了一个c ++代码:

#include<iostream>
#include<string>

using namespace std;

string s, temp;
int n, Z[1000];
int toSearchSize, poolSize, lookUpIndex[1000];
string toSearch[5] = {"string", "search", "algorithm", "best", "performance"};
string pool[9] = {"st", "se", "go", "es", "per", "123", "abcd", "e", "2"};

void joinString(){
    int idx = 0;
    for(int i = 0;i < toSearchSize;i++){
        s += toSearch[i];
        for(int j = idx;j <= idx+toSearch[i].size();j++) lookUpIndex[j] = i;
        s += "$";
        idx += toSearch[i].size()+1;
    }
    temp = s;
}

void zval(){
    int L = 0, R = 0;
    for(int i = 1;i<n;i++){
        if(i > R){
            L = R = i;
            while(R < n && s[R-L] == s[R]) R++;
            Z[i] = R-L;R--;
        }else{
            int b = R-i+1;
            if(Z[i-L] < b) Z[i] = Z[i-L];
            //else if(Z[i-L] > b) Z[i] = b;
            else{
                L = i;
                while(R < n && s[R-L] == s[R]) R++;
                Z[i] = R-L;R--;
            }
        }
    }
}

int main(){
    toSearchSize = 5, poolSize = 9;
    joinString();

    for(int i = 0;i < poolSize;i++){
        for(int j = 0;j < n;j++) Z[j] = 0;
        s = pool[i] + temp;
        n = s.size();
        zval();

        for(int j = pool[i].size();j < n;j++){
            if(Z[j] >= pool[i].size()){
                cout << "Match Found for : " << pool[i] << " in string : " << toSearch[lookUpIndex[j]] << endl;
            }
        }
    }

    return 0;
}

上述代码的输出:

Match Found for : st in string : string
Match Found for : st in string : best
Match Found for : se in string : search
Match Found for : go in string : algorithm
Match Found for : es in string : best
Match Found for : per in string : performance
Match Found for : e in string : search
Match Found for : e in string : best
Match Found for : e in string : performance
Match Found for : e in string : performance

指向Ideone上的解决方案:http://ideone.com/UGJR3i