Algorithm 选择K个相等字符串的计数方法

Algorithm 选择K个相等字符串的计数方法,algorithm,Algorithm,给定由N个小写英文字母组成的字符串S。假设我们有一个由字符串S的所有非空子字符串组成的列表L 现在我们需要回答Q问题。对于第I个查询,我需要计算从列表L中选择恰好K个相等字符串的方法的数量 注:对于每个K,我们将有不同的K值 为了避免溢出,我需要取模10^9+7 示例:设S=ababa,我们有两个查询。每个查询的K值为: 2 3 第一个查询的答案是7,第二个查询的答案是1 列表L={“a”、“b”、“a”、“b”、“a”、“ab”、“ba”、“ab”、“ba”、“aba”、“bab”、“aba

给定由N个小写英文字母组成的字符串S。假设我们有一个由字符串S的所有非空子字符串组成的列表L

现在我们需要回答Q问题。对于第I个查询,我需要计算从列表L中选择恰好K个相等字符串的方法的数量

注:对于每个K,我们将有不同的K值

为了避免溢出,我需要取模10^9+7

示例:设S=ababa,我们有两个查询。每个查询的K值为:

2
3
第一个查询的答案是7,第二个查询的答案是1

列表L={“a”、“b”、“a”、“b”、“a”、“ab”、“ba”、“ab”、“ba”、“aba”、“bab”、“aba”、“aba”、“abab”、“baba”、“aba”、“abab”、“baba”、“aba”}

对于查询1:有七种方法可以选择两个相等的字符串(“a”、“a”)、(“a”、“a”)、(“a”、“a”)、(“b”、“b”)、(“ab”、“ab”)、(“ba”、“ba”)、(“aba”、“aba”)

对于查询2:有一种方法可以选择三个相等的字符串(“a”、“a”、“a”)


现在的问题是N优化搜索的一种方法是减少成对的可能候选集

基本思想是:对于与约束匹配的长度为n>2的每个子字符串(该子字符串在输入字符串中至少出现
K
次),必须存在两个长度为n-1且符合要求的子字符串。示例:如果(“abab”、“abab”)是输入字符串的一对子字符串,则(“aba”、“aba”)和(“bab”、“bab”)也必须是输入字符串的一对子字符串

这可用于通过以下方式消除配对的候选项:
length=1
的初始子字符串集合开始,这样该集合只包含至少可以找到
K-1
相等子字符串的子字符串。通过添加下一个字符来扩展每个子字符串。现在我们可以消除子字符串,因为没有找到足够的匹配项。重复此操作,直到消除所有子字符串

现在从理论到实践:

此基本数据结构仅通过输入字符串中的起始点和结束点(包括)表示子字符串

define substr:
    int start , end
用于获取由
substr
表示的字符串的辅助方法:

define getstr:
    input: string s , substr sub

    return string(s , sub.start , sub.end)
首先为所有字符及其在字符串中的位置生成查找表。稍后需要这张桌子

define posMap:
    input: string in
    output: multimap

    multimap pos

    for int i in [0 , length(in)]
        put(pos , in[i] , i)//store the position of character in[i] in the map

    return pos
另一个助手方法生成一组在输入字符串中只出现一次的所有字符索引

define listSingle:
    input: multimap pos
    output: set

    set single
    for char c in keys(pos)
        if length(get(pos , c)) == 1
            add(single , get(get(pos , c) , 0)

    return single
创建初始匹配对集的方法。这些对由长度为1的子串组成。未指定自身的对;该算法仅将子字符串的文本映射到所有发生的事件。(注意:我在这里使用pair,尽管正确的术语应该设置为长度
K

这是完成工作的主要例行程序:

define listMatches:
    input: string in , int K
    output: multimap

    multimap chars = posMap(in)
    set single = listSingle(chars)

    multimap clvl = listSinglePairs(chars , K)

    multimap result

    while NOT isEmpty(clvl)
        multimap nextlvl

        for string sub in clvl
            list pairs = get(clvl , sub)

            list tmp

            //extend all substrings by one character
            //substrings that end in a character that only appears once in the
            //input string can be ignored
            for substr s in pairs
                if s.end + 1 > length(in) OR contains(single , s.end + 1)
                    continue

                add(tmp , substr(s.start , s.end + 1)

            //map all substrs to their respective string
            while NOT isEmpty(tmp)
                substr s = get(tmp , 0)
                string txt = getstr(s , in)

                list match = matches(in , s , chars)

                //this substring doesn't have enough pairs 
                if size(match) < K
                    continue

                //save all matches as solution and candidates for the next round
                for substr m in match
                    put(result , txt , m)
                    put(nextlvl , txt , m)

        //overwrite candidates for the next round with the given candidates
        clvl = nextlvl

    return result
定义列表匹配:
输入:字符串输入,int K
输出:多重映射
multimap chars=posMap(in)
设置单个=列表单个(字符)
multimap clvl=listSinglePairs(字符,K)
多重映射结果
虽然不是空的(clvl)
多重映射nextlvl
对于clvl中的字符串sub
列表对=获取(clvl,sub)
列出tmp
//将所有子字符串扩展一个字符
//以字符结尾的子字符串,该字符在
//可以忽略输入字符串
对于成对的substr s
如果s.end+1>长度(英寸)或包含(单个,s.end+1)
持续
添加(tmp、substr(s.start、s.end+1)
//将所有子字符串映射到各自的字符串
虽然不是空的(tmp)
substr s=get(tmp,0)
字符串txt=getstr(s,in)
列表匹配=匹配项(in、s、chars)
//此子字符串没有足够的对
如果尺寸(匹配)
注意:此算法生成所有子字符串的映射,对于这些子字符串,存在子字符串位置的对


我希望这是可以理解的(我解释得很糟糕)。

我想我明白你的意思了。你能告诉我这个算法每个查询花费的时间吗?@python\u slayer我在运行时分析方面真的很差,但我认为最坏的情况是
匹配项为O(n^2),而
列表匹配项为O(n^4)
define matches:
    input: string in , substr sub , multimap charmap
    output: list

    list result

    string txt = getstr(in , sub)

    list candidates = get(charmap , txt[0])

    for int i in [1 , length(txt)[
        //increment all elements in candidates
        for int c in [0 , size(candidates)[
            replace(candidates , c , get(candidates , c) + 1)

        list next = get(charmap , txt[i])

        //since the indices of all candidates were incremented (index of the previous character in
        //in) they now are equal to the indices of the next character in the substring, if it matches
        candidates = intersection(candidates , next)

        if isEmpty(candidates)
            return EMPTY

    //candidates now holds the indices of the end of all substrings that
    //match the given substring -> convert to list of substr
    for int i in candidates
        add(result , substr(i - length(txt) , i))

    return result
define listMatches:
    input: string in , int K
    output: multimap

    multimap chars = posMap(in)
    set single = listSingle(chars)

    multimap clvl = listSinglePairs(chars , K)

    multimap result

    while NOT isEmpty(clvl)
        multimap nextlvl

        for string sub in clvl
            list pairs = get(clvl , sub)

            list tmp

            //extend all substrings by one character
            //substrings that end in a character that only appears once in the
            //input string can be ignored
            for substr s in pairs
                if s.end + 1 > length(in) OR contains(single , s.end + 1)
                    continue

                add(tmp , substr(s.start , s.end + 1)

            //map all substrs to their respective string
            while NOT isEmpty(tmp)
                substr s = get(tmp , 0)
                string txt = getstr(s , in)

                list match = matches(in , s , chars)

                //this substring doesn't have enough pairs 
                if size(match) < K
                    continue

                //save all matches as solution and candidates for the next round
                for substr m in match
                    put(result , txt , m)
                    put(nextlvl , txt , m)

        //overwrite candidates for the next round with the given candidates
        clvl = nextlvl

    return result