给出三个字符串序列“abb”“ab”“a”。
现在我需要找到算法来检查字符串是否可以通过上面的序列解析。例如
字符串“abbabab”可以通过序列“abb”“ab”和“ab”解析
字符串“abbbaaa”它无法解析,因为我们没有“b”序列。
我已经编写了以下代码,但我觉得它不是正确的算法。任何建议。
bool checkIsStringCanBeParsed(std::string S) {
std::string seqArray[6]={"abb","ab","a","abb","ab","a"};
int index=0;
int lastIndex=0;
for(int i=0;i<6;++i)
{
lastIndex =index;
for(int idx=0;idx<seqArray[i].length();++idx)
{
if(index >= S.length())
{
index =lastIndex;
break;
}
if(S[index] == seqArray[i][idx])
{
++index;
continue;
}
else
break;
}
if(index == S.length())
return true;
}
return false;
}
答案 0 :(得分:1)
您要做的是构建一个接受表达式(abb | ab | a)*中的句子的正则表达式引擎,一个选项是使用non deterministic automata来表示该正则表达式。使用此tool我能够生成:
这里我们有一个包含3个状态的图表。当您想要查看规则是否接受给定字符串时,它必须被此图表接受,通过接受它意味着通过char读取字符串char,您应该能够使用有效步骤在图表中导航。解析字符串时,应始终从状态0开始。
例如字符串“aaba”将引导我们进入状态0,状态1,状态1,状态2,状态1,因此字符串是有效的,因为我们能够完全解析它。字符串“abbb”将引导我们进入状态0,状态1,状态2,状态3但是没有办法从状态3使用另一个'b',因此该字符串无效。
伪代码执行此操作:
boolean accept(word, state)
{
if(word.length == 0) //either the string is empty or the parsing has ended succesfully
{
return true;
}
else
{
parsingChar = word[0] //first char of string
switch state
case 0:
if (parsingChar == 'a')
return accept(substring(word,1),1); //recursive call, we remove the first char and move to state 1
else
return false; // the first char is not an 'a' the word is not accepted
break;
case 1:
if (parsingChar == 'a')
return accept(substring(word,1),3); // move to state 3
else if (parsingChar == 'b')
return accept(substring(word,1),2); // move to state 2
else
return false; //
break;
case 2:
if (parsingChar == 'a')
return accept(substring(word,1),3); // move to state 3
else if (parsingChar == 'b')
return accept(substring(word,1),1); // move to state 1
else
return false; //
break;
case 3:
if (parsingChar == 'a')
return accept(substring(word,1),1); // move to state 1
else
return false;
break;
}
}
答案 1 :(得分:0)
你应该使用正则表达式。序列的正则表达式是“^((abb)|(ab)|(a))* $”。正则表达式库将为您优化它。
答案 2 :(得分:0)
动态编程应该可以正常工作。假设dp(i)= true,当且仅当有可能用给定序列解析长度为i的前缀时。最初,dp(0)=真。然后可以通过以下方式计算所有i的dp值:如果dp(j)= true并且从j + 1到i的子串匹配其中一个序列,则dp(i)= true。