頭に浮かぶ最初の解決策は、再帰的なメソッドを作成することです。
再帰的方法
recursiveメソッドは文字列を受け取り、それを並べ替える方法の数を返します。
ベースケース:
基本ケース:文字列に「{」と「}」がない場合は、「|」の数を返します。文字列の記号に1を加えたもの。
それ以外の場合:
最初の「{」の位置を見つけ、それをPos1と呼びます。
対応する「}」を見つけて、Pos2と呼びます。
ここで、3つのサブストリング[0からPos1)、(Pos1からPos2)、(Pos2からEnd]を形成します。
Pos1とPos2はサブストリングに含まれていないため、2つの中括弧が失われることに注意してください。
各部分文字列の繰り返しの積/合計を返します。
上記のアルゴリズムを示すC#コードは次のとおりです。
static void Main(string[] args)
{
string test1 ="{abc|{cde|fgh}} aaa {cde|fg}.";
int numWays = getNumWaysRecursive(test1);
Console.WriteLine("NumWays: " + numWays);
Console.ReadLine();
}
private static int getNumWaysRecursive( string s )
{
if (s == null) return 1;
if (s == "") return 1;
int firstBracePos = s.IndexOf('{');
if (firstBracePos == -1) //Base case, no braces.
{
int pipeCount = 0;
for (int i = 1; i < s.Length - 1; i++)
{
if (s[i] == '|')
{
if (pipeCount == -1)
{
pipeCount = 0;
}
pipeCount++;
}
}
return pipeCount + 1;
}
//Non-Base case:
// find the first Left Brace
// find the right brace it corresponds with
int numOfNests = 0;
int pos = firstBracePos + 1;
while (pos < s.Length)
{
if (s[pos] == '}')
{
numOfNests--;
if (numOfNests == -1)
{
break;
}
}
else if (s[pos] == '{')
{
numOfNests++;
}
pos++;
}
//Get rid of those braces, and recurse on the three parts:
// 1. the part before the braces.
// 2. the part between the braces.
// 3. the part after the braces.
string firstPart;
if (firstBracePos == 0)
{
firstPart = "";
}
else
{
firstPart = s.Substring(0, firstBracePos);
}
string secondPart = s.Substring(firstBracePos + 1, pos - firstBracePos - 1);
string lastPart = s.Substring(pos + 1 );
int sum1 = getNumWaysRecursive(firstPart);
int sum2 = getNumWaysRecursive(secondPart);
int sum3 = getNumWaysRecursive(lastPart);
bool strng1HasPipes = (firstPart.IndexOf('|') != -1);
int sum = 1;
if ( strng1HasPipes )
{
sum += sum1 - 1;
sum += sum2;
}
else
{
sum *= sum2;
}
if (sum3 == 0)
{
;
}
else
{
sum *= sum3;
}
return sum;
}
残念ながら、これは全体の状況を完全に捉えているわけではありません。
「{abc|{cde | fgh}} aaa {cde | fg} eee | {abc|bbb}」のような文字列では失敗します。
中括弧内にネストされていないため、最後から2番目のパイプシンボルのネスト位置が完全には理解されていないためです。
したがって、文字列の初期スキャンを実行し、「|」に基づいてサブ文字列に分割する必要があります。中括弧内にない記号は、それらの部分文字列の小計を合計します。