给定单词和文本,返回文本中单词字符的出现次数。 例如。单词是“for”,文本是“forxxorfxdofr”,“for”的字谜将是“ofr”,“orf”,“fro”等等。所以对于这个特例,答案是3。
我有蛮力方法获得该词的所有排列,然后比较文本是否包含它,并增加出现次数,但这是O(N ^ 2)方法。我正在寻找更好的复杂性。
答案 0 :(得分:13)
您只需查找字符数即可。
比如说你正在寻找look
的字谜。所以,你正在寻找:
只需处理前4个字母,存储计数。检查您是否匹配。 添加下一个字符(增量),删除旧字符(减量)。再检查一遍。 等等...
答案 1 :(得分:3)
TooTone's O(n) solution必须为输入文本的每个字符比较两个256元素向量。这可以通过跟踪两个矢量不同的位置的数量来避免,并且当该数字变为零时记录匹配。事实上,我们甚至根本不需要存储两个不同的向量,因为我们可以存储一个包含它们差异的向量。
这是我实现这些优化的版本。它是用普通的旧C语言编写的,但应该在C ++下进行适当的调整:
#include <stdio.h>
#include <limits.h> /* for UCHAR_MAX (usually 255) */
int find_anagrams (char *word, char *text) {
int len = 0; /* length of search word */
int bin[UCHAR_MAX+1]; /* excess count of each char in last len chars of text */
int mismatch = 0; /* count of nonzero values in bins[] */
int found = 0; /* number of anagrams found */
int i; /* generic loop counter */
/* initialize bins */
for (i = 0; i <= UCHAR_MAX; i++) bin[i] = 0;
for (i = 0; word[i] != '\0'; i++) {
unsigned char c = (unsigned char) word[i];
if (bin[c] == 0) mismatch++;
bin[c]--;
len++; /* who needs strlen()? */
}
/* iterate through text */
for (i = 0; text[i] != '\0'; i++) {
/* add next char in text to bins, keep track of mismatch count */
unsigned char c = (unsigned char) text[i];
if (bin[c] == 0) mismatch++;
if (bin[c] == -1) mismatch--;
bin[c]++;
/* remove len-th previous char from bins, keep track of mismatch count */
if (i >= len) {
unsigned char d = (unsigned char) text[i - len];
if (bin[d] == 0) mismatch++;
if (bin[d] == 1) mismatch--;
bin[d]--;
}
/* if mismatch count is zero, we've found an anagram */
if (mismatch == 0) {
found++;
#ifdef DEBUG
/* optional: print each anagram found */
printf("Anagram found at position %d: \"", i-len+1);
fwrite(text+i-len+1, 1, len, stdout);
printf("\"\n");
#endif
}
}
return found;
}
int main (int argc, char *argv[]) {
if (argc == 3) {
int n = find_anagrams(argv[1], argv[2]);
printf("Found %d anagrams of \"%s\" in \"%s\".\n", n, argv[1], argv[2]);
return 0;
} else {
fprintf(stderr, "Usage: %s <word> <text>\n", (argc ? argv[0] : "countanagrams"));
return 1;
}
}
答案 2 :(得分:2)
基本上,您可以在输入上滑动单词长度的窗口,并计算窗口中每个字母的数量。当滑动窗口中的字母数与您单词的字母数相匹配时,您就会匹配。
让您的字长为n
,您当前的位置为curr
。创建一个长度为26的数组或vector
,windCounts
。条目windCounts[i]
存储从位置看到的字母i th 字母的出现次数curr - n - 1
至curr
。
你所做的就是提前curr
,并通过减少从滑动窗口后面掉落的字母,并增加字母数量,使数组windCounts
保持最新状态。已经出现在滑动窗口的前面。 (显然,直到curr
&gt; n
,你只需增加,你只需按照你的单词长度建立你的滑动窗口。)
在C ++中,您可以使用vector
表示单词中的字母数,以及滑动窗口中的字母数,只需使用vector::operator==
即可。
编辑:算法为O(N)
,其中N
是要搜索的文本的长度。这可以从下面的代码中看到,其中为您滑动窗口的每个字母执行循环体。
#include <string>
#include <vector>
#include <algorithm> // for_each
using std::string;
using std::vector;
#include <iostream>
int main(int argc, char* argv[])
{
const string text = "forxxorfxdofr";
const string word = "for";
// Counts of letters in word
vector<int> wordCounts(256); // optimization: cut down from 256 to 26
std::for_each(word.begin(), word.end(),
[&] (char c) { wordCounts[c]++; } );
// Current position of end of sliding window
string::const_iterator curr = text.begin() + word.size();
// Initial sliding window counts
vector<int> windCounts(256);
std::for_each(text.begin(), curr,
[&] (char c) { windCounts[c]++; } );
// Run sliding window over text
int numMatches = 0;
while (1) {
numMatches += wordCounts == windCounts;
if (curr == text.end()) {
break;
}
windCounts[*(curr - word.size())]--;
windCounts[*curr]++;
++curr;
}
std::cout << numMatches << "\n";
return 0;
}
答案 3 :(得分:0)
我有两个字符串即str和occ。 Str是原始的strin和occ是我们必须找到计数的刺痛。使用strncpy函数我已经将occ的长度,即n个字符复制到一个临时数组中,然后检查它是否是一个occ字符串的排列。
#include<iostream.h>
#include<conio.h>
#include<string.h>
int permutate(char str1[],char str2[]);
int permutate(char str1[],char str2[]) {
int c[256]={0},i,j;
for(i=0;i<strlen(str1);i++)
c[str1[i]]++;
for(i=0;i<strlen(str2);i++) {
c[str2[i]]--;
if(c[str2[i]]<0)
return 1; //not a permutation
}
return 0; //permutation
}
int main() {
//enter code here
char str[]="forxxorfxdofr",occ[]="for",temp[10];
int n,i,x,t=0;
n=strlen(occ);
for(i=0;i<strlen(str);i++) {
strncpy(temp,str+i,n); //copy the n char from str to temp
x=permutate(temp,occ);
if(x==0) //if string is a permutation
t++;
}
cout<<"Count = " << t;
return 0;
}
答案 4 :(得分:0)
o(n) solution in Python
def检查(s1,s2):
function takes in s1 as the text and s2 as the text to be checked from here for
c=0
n=len(s2)
ck=sorted(s2)
mk=''.join(ck)
this loop will pick from s till the length of s2 that is 'for'
for i,item in enumerate(s1):
if s1[i] in mk:
p=s1[i:i+n]
jk=sorted(p)
er=''.join(jk)
now just comparing the both sorted strings if they are equal then they were anagram
if er == mk:
c+=1
return c