String 有趣字符串算法

String 有趣字符串算法,string,algorithm,sequences,String,Algorithm,Sequences,给定两个长度分别为n的有限字符串序列A和B, 例如: A1: "kk", A2: "ka", A3: "kkk", A4: "a" B1: "ka", B2: "kakk", B3: "ak", B4: "k" 给出一个索引的有限序列,使其集中于 B给出了相同的字符串。允许重复 在本例中,我找不到解决方案,但例如,如果列表(1,2,2,4)是一个解决方案,则A1+A2+A2+A4=B1+B2+B2+B4。在这个例子中,只有两个字符,但已经很难了。事实上,用一个字符找到最短的解决方案甚至不是一

给定两个长度分别为
n
的有限字符串序列
A
B
, 例如:

A1: "kk", A2: "ka", A3: "kkk", A4: "a"

B1: "ka", B2: "kakk", B3: "ak", B4: "k"
给出一个索引的有限序列,使其集中于 B给出了相同的字符串。允许重复

在本例中,我找不到解决方案,但例如,如果列表
(1,2,2,4)
是一个解决方案,则
A1+A2+A2+A4=B1+B2+B2+B4
。在这个例子中,只有两个字符,但已经很难了。事实上,用一个字符找到最短的解决方案甚至不是一件小事

我试着去想事情。。例如,字符串长度的总和必须相等,对于第一个和最后一个字符串,我们需要相应的字符。但没有别的。我想对于某些字符串集来说,这根本是不可能的。谁能想出一个好的算法

编辑:显然,这是


没有算法可以决定这样一个实例是否有解决方案。如果有,停车问题可以解决。肮脏的把戏…

这个问题很难回答,但我会试一试。这更多的是一种意识流,而不是一个事先道歉的回答

如果我理解正确的话,你会得到两个大小相等的字符串序列,A和B,从1..n开始索引。然后,您必须找到一个索引序列,使得字符串a(1)…a(m)的串联等于字符串B(1)…B(m)的串联,其中m是索引序列的长度

我观察到的第一件事是,可能有无限多的解。例如,假设:

A{“x”,“xx”}
B{“xx”,“x”}

可能的解决办法是:

{1,2}
{2,1}
{1,2,1,2}
{1,2,2,1}
{2,1,1,2}
{2,1,2,1}
{1,2,1,2,1,2}

那你怎么知道什么时候该停下来?只要你有一个解决方案?只要一个解是另一个解的超集

您可以从两个集合中取最小公共长度的所有字符串开始(在我上面的示例中,您可以取“x”然后,您可以对下一个大小的字符串重复此操作。例如,如果第一个集合有3个长度分别为1、2和3的字符串,而第二个集合有3个长度分别为1、3和3的字符串,则您将获取长度为3的字符串。您可以这样做,直到没有更多字符串。如果您找到任何字符串,那么您就有了问题的解决方案

然后,当您必须开始组合多个字符串(如我上面的示例中所示)时,情况会变得更加困难。天真、暴力的方法是开始排列两个集合中的所有字符串,当连接时,这些字符串会产生相同长度的字符串,然后对它们进行比较。因此,在下面的示例中:

A{“ga”、“bag”、“ac”、“A”}
B{“ba”、“g”、“ag”、“gac”}

您可以从长度为2的序列开始:

A{“ga”,“ac”},B{“ba”,“ag”}(指数1,3)
A{“bag”,“A},B{“g”,“gac}(指数2,4)

比较得出“gaac”与“baag”以及“baga”与“ggac”,两者都不相等,因此没有解决方案。接下来,我们将讨论长度为3的序列:

A{“ga”,“bag”,“A”},B{“ba”,“g”,“gac”}(指数1,2,4)
A{“bag”、“ac”、“A”},B{“g”、“ag”、“gac”}(指数2、3、4)

同样,没有解,所以我们最终得到大小为4的序列,其中我们没有解

现在它变得更加棘手,因为我们必须开始考虑重复一些指数,现在我的大脑正在融化


我想在字符串中寻找公共子序列可能会有所帮助,然后使用字符串中未匹配的其余部分。但我不太清楚如何使用。

一个非常简单的方法就是使用类似广度优先搜索的方法。这还有一个优点,即找到的第一个解决方案的大小最小。

H建议使用暴力搜索。首先生成与列表长度相关的数字序列:

[0,0,…] [1,0,..] [2,0,..] [3,0,..] [0,1,..]

数字序列长度决定在找到的任何解决方案中有多少字符串。 然后使用数字作为字符串列表的索引生成A和B字符串:

public class FitSequence 
{
    private readonly string[] a;
    private readonly string[] b;

    public FitSequence(string[] a, string[] b)
    {
        this.a = a;
        this.b = b;
    }

    private static string BuildString(string[] source, int[] indexes)
    {
        var s = new StringBuilder();
        for (int i = 0; i < indexes.Length; ++i)
        {
            s.Append(source[indexes[i]]);
        }
        return s.ToString();
    }

    public IEnumerable<int[]> GetSequences(int length)
    {
        foreach (var numberSequence in new NumberSequence(length).GetNumbers(a.Length - 1))
        {
            string a1 = BuildString(a, numberSequence);
            string b1 = BuildString(b, numberSequence);
            if (a1 == b1)
                yield return numberSequence;
        }
    }
}
公共类序列
{
私有只读字符串[]a;
私有只读字符串[]b;
公共序列(字符串[]a,字符串[]b)
{
这个a=a;
这个.b=b;
}
私有静态字符串BuildString(字符串[]源,int[]索引)
{
var s=新的StringBuilder();
for(int i=0;i
该算法假定A和B的长度相等。 我测试了你的例子

    static void Main(string[] args)
    {
        var a = new[] {"kk", "ka", "kkk", "a"};
        var b = new[] {"ka", "kakk", "ak", "k"};
        for (int i = 0; i < 100; ++i)
            foreach (var sequence in new FitSequence(a, b).GetSequences(i))
            {
                foreach (int x in sequence)
                    Console.Write("{0} ", x);
                Console.WriteLine();
            }
    }
static void Main(字符串[]args)
{
var a=新[]{“kk”、“ka”、“kkk”、“a”};
var b=新[]{“ka”、“kakk”、“ak”、“k”};
对于(int i=0;i<100;++i)
foreach(新FitSequence(a,b)中的var序列。GetSequences(i))
{
foreach(按顺序输入x)
Console.Write(“{0}”,x);
Console.WriteLine();
}
}

但是找不到任何解决方案,尽管它似乎适用于简单的测试。

不清楚您要寻找的“解决方案”是什么,最长的解决方案?最短的解决方案?所有解决方案?
既然你允许在那里重复
// assumed true/false functions

let Eq aList bList =  
// eg Eq "ab"::"c" "a" :: "bc" -> true
// Eq {} {} is _false_

let EitherStartsWith aList bList =  
// eg "ab"::"c" "a" :: "b" -> true
// eg "a" "ab" -> true
// {} {} is _true_    

let rec FindMatches A B aList bList level
    = seq {
        if level > 0
            if Eq aList bList
                yield aList
            else if EitherStartsWith aList bList
                Seq.zip3 A B seq {1..} 
                |> Seq.iter (func (a,b,i) -> 
                    yield! FindMatches A B aList::(a,i) bList::(b,i) level - 1) }

let solution (A:seq<string>) (B:seq<string>) length =
    FindMatches A B {} {} length
let solution (A:seq<string>) (B:seq<string>) length =
    let starts = {}
    let ends = {}
    Seq.zip3 A B seq {1..} 
    |> Seq.iter(fun (a,b,i) -> 
        if (a.StartsWith(b) or b.StartsWith(a))
            start = starts :: (a,b,i)
        if (a.EndsWith(b) or b.EndsWith(a))
            ends = ends :: (a,b,i))

    if List.is_empty starts || List.is_empty ends
        Seq.empty // no solution
    else
        Seq.map (fun (a,b,i) -> 
            FindMatches A B {} :: (a,i) {} :: (b,i) length - 1)
        starts 
        |> Seq.concat