Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 查找字符串列表中相同位置的字符的算法?_Algorithm_String - Fatal编程技术网

Algorithm 查找字符串列表中相同位置的字符的算法?

Algorithm 查找字符串列表中相同位置的字符的算法?,algorithm,string,Algorithm,String,假设我有: 托比 微小的 保守党 蒂利 是否有一种算法可以轻松创建所有这些字符串中相同位置的常用字符列表?(在这种情况下,常用字符是位置0处的“T”和位置3处的“y”) 我试着研究了一些用于DNA序列匹配的算法,但似乎大多数算法只是用于查找公共子字符串,而不管它们的位置如何。在某个位置查找所有字符串中公共的字符列表非常简单。只需对每个字符位置的每个字符串一次迭代一个字符位置。如果任何字符串的字符与其最近相邻字符串的字符不匹配,则该位置不包含公共字符 #include <iostream&g

假设我有:

  • 托比
  • 微小的
  • 保守党
  • 蒂利
  • 是否有一种算法可以轻松创建所有这些字符串中相同位置的常用字符列表?(在这种情况下,常用字符是位置0处的“T”和位置3处的“y”)


    我试着研究了一些用于DNA序列匹配的算法,但似乎大多数算法只是用于查找公共子字符串,而不管它们的位置如何。

    在某个位置查找所有字符串中公共的字符列表非常简单。只需对每个字符位置的每个字符串一次迭代一个字符位置。如果任何字符串的字符与其最近相邻字符串的字符不匹配,则该位置不包含公共字符

    #include <iostream>
    
    int main(void)
    {
        char words[4][5] = 
        {
            "Toby",
            "Tiny",
            "Tory",
            "Tily"
        };
    
        int wordsCount = 4;
        int lettersPerWord = 4;
    
        int z;
        for (z = 1; z < wordsCount; z++)
        {
            int y;
            for (y = 0; y < lettersPerWord; y++)
            {
                if (words[0][y] != words[z][y])
                {
                    words[0][y] = ' ';
                }
            }
        }
    
        std::cout << words[0] << std::endl;
    
        return 0;
    }
    
    对于长度为-1的任何i=0。。。一旦找到Si[x]!=Si+1[x]您可以跳到下一个位置x+1


    其中Si是列表中的第i个字符串。[x]是位置x处的字符。

    一些性能非常差的通用代码O(n^2)

    str[]={“托比”、“蒂尼”、“托利”、“蒂利”};
    结果=空;
    largestString=str.getLargestString();//组合函数
    str.remove(最大字符串)
    对于(i=0;i
    我想不出任何特别优化的东西

    你可以这样做,这应该不会太难:

            //c# -- assuming your strings are in a List<string> named Names
            int shortestLength = Names[0].Length, j;
            char[] CommonCharacters;
            char single;
    
            for (int i = 1; i < Names.Count; i++)
            {
                if (Names[i].Length < shortestLength) shortestLength = Names[i].Length;
            }
    
            CommonCharacters = new char[shortestLength];
            for (int i = 0; i < shortestLength; i++)
            {
                j = 1;
                single = Names[0][i];
                CommonCharacters[i] = single;
                while (j < shortestLength)
                {
                    if (single != Names[j][i])
                    {
                        CommonCharacters[i] = " "[0];
                        break;
                    }
                    j++;
                }
            }
    
    /c#——假设字符串位于名为name的列表中
    int shortestLength=名称[0]。长度,j;
    字符[]公共字符;
    单焦;
    for(int i=1;i

    这将为您提供一个在列表中所有内容上都相同的字符数组。

    这样的东西怎么样

    strings = %w(Tony Tiny Tory Tily)
    positions = Hash.new { |h,k| h[k] = Hash.new { |h,k| h[k] = 0 } }
    strings.each { |str| 
      0.upto(str.length-1) { |i| 
        positions[i][str[i,1]]+=1 
      }
    }
    
    在执行结束时,结果将是:

    positions = {
      0=>{"T"=>4},
      1=>{"o"=>2, "i"=>2}, 
      2=>{"l"=>1, "n"=>2, "r"=>1},
      3=>{"y"=>4}
    }
    

    以下是5行ruby中的一个算法:

    #!/usr/bin/env ruby
    chars = STDIN.gets.chomp.split("")
    STDIN.each do |string|
      chars = string.chomp.split("").zip(chars).map {|x,y| x == y ? x : nil }
    end
    chars.each_index {|i| puts "#{chars[i]}  #{i}" if chars[i] }
    
    把这个放在commonletters.rb中。示例用法:

    $ commonletters.rb < input.txt
    T  0
    y  3
    

    这应该适用于您向其抛出的任何输入。如果输入文件为空,它将中断,但您可以自己修复。这是O(n)(n是输入中的字符总数)。

    这里是Python的一个简单版本:

    items = ['Toby', 'Tiny', 'Tory', 'Tily']
    tuples = sorted(x for item in items for x in enumerate(item))
    print [x[0] for x in itertools.groupby(tuples) if len(list(x[1])) == len(items)]
    
    其中打印:

    [(0, 'T'), (3, 'y')]
    
    编辑:这里有一个更好的版本,不需要创建(可能)庞大的元组列表:

    items = ['Toby', 'Tiny', 'Tory', 'Tily']
    minlen = min(len(x) for x in items)
    print [(i, items[0][i]) for i in range(minlen) if all(x[i] == items[0][i] for x in items)]
    
    在lisp中:

    CL-USER> (defun common-chars (&rest strings)
               (apply #'map 'list #'char= strings))
    COMMON-CHARS
    
    只需传入字符串:

    CL-USER> (common-chars "Toby" "Tiny" "Tory" "Tily")
    (T NIL NIL T)
    
    如果您想要字符本身:

    CL-USER> (defun common-chars2 (&rest strings)
               (apply #'map
                      'list
                      #'(lambda (&rest chars)
                          (when (apply #'char= chars)
                            (first chars))) ; return the char instead of T
                      strings))
    COMMON-CHARS2
    
    CL-USER> (common-chars2 "Toby" "Tiny" "Tory" "Tily")
    (#\T NIL NIL #\y)
    
    如果您不关心posiitons,只需要一个常见字符列表:

    CL-USER> (format t "~{~@[~A ~]~}" (common-chars2 "Toby" "Tiny" "Tory" "Tily"))
    T y 
    NIL
    
    我承认这不是一个算法。。。这只是一种使用现有功能在lisp中实现的方法

    如前所述,如果要手动执行此操作,可以循环比较给定索引中的所有字符。如果它们都匹配,请保存匹配的字符。

    \include
    
    #include <iostream>
    
    int main(void)
    {
        char words[4][5] = 
        {
            "Toby",
            "Tiny",
            "Tory",
            "Tily"
        };
    
        int wordsCount = 4;
        int lettersPerWord = 4;
    
        int z;
        for (z = 1; z < wordsCount; z++)
        {
            int y;
            for (y = 0; y < lettersPerWord; y++)
            {
                if (words[0][y] != words[z][y])
                {
                    words[0][y] = ' ';
                }
            }
        }
    
        std::cout << words[0] << std::endl;
    
        return 0;
    }
    
    内部主(空) { 字符字[4][5]= { “托比”, “小”, “保守党”, “蒂利” }; int-wordscont=4; int-lettersPerWord=4; intz; 对于(z=1;z库特,这就是为什么我喜欢ruby的声音。让你快速完成事情。
    #include <iostream>
    
    int main(void)
    {
        char words[4][5] = 
        {
            "Toby",
            "Tiny",
            "Tory",
            "Tily"
        };
    
        int wordsCount = 4;
        int lettersPerWord = 4;
    
        int z;
        for (z = 1; z < wordsCount; z++)
        {
            int y;
            for (y = 0; y < lettersPerWord; y++)
            {
                if (words[0][y] != words[z][y])
                {
                    words[0][y] = ' ';
                }
            }
        }
    
        std::cout << words[0] << std::endl;
    
        return 0;
    }