例如。单词为for
,文字为forxxorfxdofr
,for
的字谜将为ofr
,orf
,fro
等。所以答案是对于这个特定的例子来说是3
。
这是我想出的。
#include<iostream>
#include<cstring>
using namespace std;
int countAnagram (char *pattern, char *text)
{
int patternLength = strlen(pattern);
int textLength = strlen(text);
int dp1[256] = {0}, dp2[256] = {0}, i, j;
for (i = 0; i < patternLength; i++)
{
dp1[pattern[i]]++;
dp2[text[i]]++;
}
int found = 0, temp = 0;
for (i = 0; i < 256; i++)
{
if (dp1[i]!=dp2[i])
{
temp = 1;
break;
}
}
if (temp == 0)
found++;
for (i = 0; i < textLength - patternLength; i++)
{
temp = 0;
dp2[text[i]]--;
dp2[text[i+patternLength]]++;
for (j = 0; j < 256; j++)
{
if (dp1[j]!=dp2[j])
{
temp = 1;
break;
}
}
if (temp == 0)
found++;
}
return found;
}
int main()
{
char pattern[] = "for";
char text[] = "ofrghofrof";
cout << countAnagram(pattern, text);
}
对于上述问题,是否存在更快的算法?
答案 0 :(得分:0)
大部分时间都用于搜索,因此为了使算法更具时间效率,目标是减少搜索量或优化搜索。
创建一个列表向量,每个字母表的一个向量槽。这可以在以后进行空间优化。
每个插槽都会包含文本中的索引列表。
示例文字:forxxorfxdofr
Slot List
'f' 0 --> 7 --> 11
'o' 1 --> 5 --> 10
'r' 2 --> 6 --> 12
对于每个单词,在向量中查找字母以获取文本中的索引列表。对于列表中的每个索引,将列表项中的文本字符串位置与单词进行比较。
因此,使用上表和单词“ofr”,第一次比较发生在索引1处,第二次比较发生在索引5处,最后一次比较发生在索引10处。
你可以消除文本索引的近端(索引+字长&gt;文本长度)。
答案 1 :(得分:0)
你可以使用乘法的可交换性,以及原始分解的唯一性。这取决于我之前的回答here
创建从每个字符到素数列表的映射(尽可能小)。对于例如a - &gt; 2,b - &gt; 3,c - &gt; 5等。这可以保存在一个简单的数组中。
现在,将给定的单词转换为与其每个字符匹配的素数的乘法。这个结果将等于该词的任何字谜的类似乘法。
现在扫过数组,并在任何给定的步骤中,保持与最后L个字符匹配的素数的乘法(其中L是单词的长度)。所以,每次你前进,
mul = mul * char2prime(text[i]) / char2prime(text[i-L])
每当这个乘法等于你的单词时 - 增加整个计数器,你就完成了
请注意,此方法适用于短字,但素数乘法可以很快地溢出64b var(大约9-10个字母),因此您必须使用大量数学库来支持更长的单词
答案 2 :(得分:-1)
如果要设计的图案太短以至于搜索它的最佳方式是简单地扫描它,那么该算法是相当有效的。为了允许更长的模式,此处由“for jj
”和“for mm
”循环表示的扫描可以被更复杂的搜索技术所取代。
// sLine -- string to be searched
// sWord -- pattern to be anagrammed
// (in this pseudo-language, the index of the first character in a string is 0)
// iAnagrams -- count of anagrams found
iLineLim = length(sLine)-1
iWordLim = length(sWord)-1
// we need a 'deleted' marker char that will never appear in the input strings
chNil = chr(0)
iAnagrams = 0 // well we haven't found any yet have we
// examine every posn in sLine where an anagram could possibly start
for ii from 0 to iLineLim-iWordLim do {
chK = sLine[ii]
// does the char at this position in sLine also appear in sWord
for jj from 0 to iWordLim do {
if sWord[jj]=chK then {
// yes -- we have a candidate starting posn in sLine
// is there an anagram of sWord at this position in sLine
sCopy = sWord // make a temp copy that we will delete one char at a time
sCopy[jj] = chNil // delete the char we already found in sLine
// the rest of the anagram would have to be in the next iWordLim positions
for kk from ii+1 to ii+iWordLim do {
chK = sLine[kk]
cc = false
for mm from 0 to iWordLim do { // look for anagram char
if sCopy[mm]=chK then { // found one
cc = true
sCopy[mm] = chNil // delete it from copy
break // out of 'for mm'
}
}
if not cc then break // out of 'for kk' -- no anagram char here
}
if cc then { iAnagrams = iAnagrams+1 }
break // out of 'for jj'
}
}
}
-Al。