给定一个单词和一个文本,我们需要返回字谜的出现次数
Given a word and a text, we need to return the occurrences of anagrams
给定一个单词和一个文本,返回文本中单词字谜的出现次数。例如。单词是"for",文本是"forxxorfxdofr","for"的字谜将是"ofr","orf","fro"等。因此,对于这个特定示例,答案将是 3。
我有蛮力方法,它获取单词的所有排列,然后比较文本是否包含它,并增加出现次数,但这是 O(N^2) 方法。我正在寻找更好的复杂性。
您可以简单地查找字符数。
例如,假设您正在寻找look
字谜。因此,您正在寻找:
- 一个4个字符长的单词,
- 使用 1 L、2 O 和 1 K。
只需处理前 4 个字母,存储计数。检查您是否有匹配项。添加下一个字符(递增),删除旧字符(递减)。再次检查。等等...
TooTone的O(n)解决方案必须为输入文本的每个字符比较两个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] != ' '; 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] != ' '; 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;
}
}
从本质上讲,您可以在输入上滑动单词长度的窗口,并计算窗口中每个字母的数量。当滑动窗口中的字母计数与单词的字母计数匹配时,您就有了匹配项。
让你的字长n
,你现在的位置curr
。创建一个数组,或vector
,windCounts
长度为 26。条目windCounts[i]
存储从位置 curr - n - 1
到 curr
看到的字母表中第 i 个字母的出现次数。
您要做的是前进curr
,并通过减少从滑动窗口背面掉出的字母并增加出现在滑动窗口前面的字母计数来使数组windCounts
最新。(显然,直到curr
> 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;
}
我取了两个字符串,即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;
}
o(n) solution in Python
定义检查(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
在C++的解决方案。
它将生成所有排列替换为对单词和字符串的一部分进行排序。
cin >> sstring;
cin >> word;
ocurrences = 0;
sort(word.begin(), word.end());
for (int i = 0; i < sstring.size(); i++)
{
string copy = sstring.substr(i, word.size());
sort(copy.begin(), copy.end());
if (word == copy)
{
ocurrences++;
}
}
cout << ocurrences << endl;
- C++,class,一个返回对象的函数
- C++ 这里有一个返回 (24) 的布尔返回类型函数
- 我有一个返回字符串向量的函数.它需要两个字符串,并且返回一个字符串中缺少的字符串
- 两个相同的重载运算符[]一个返回引用
- 给定一个整数 N>0,区间 [0, 2^N) 中有多少个整数正好有 N-1 个设置位?编写一个返回正确答案的简短函数
- 为什么要定义一个返回结构的 lambda 函数,而不是直接定义结构
- 有没有办法重写一个返回指向 istringstream 的指针的函数,而不是返回一个引用?
- 提升:创建一个返回变体的函数
- C++重载运算符两次,一个返回非常量引用,另一个返回常量引用,首选项是什么
- 我是否应该将最后一个“返回”语句封装为“else { return .. }',如果它在逻辑上是可选的
- 野牛解析器:创建一个返回令牌的函数
- 为什么 C++ 数组的大小不能有一个返回常量的函数调用
- 如何创建一个返回传递的参数名称的函数
- 如何在C++中创建一个返回字节数组的函数?Arduino项目
- 将返回的指针分配给另一个返回的指针
- 如何声明一个返回类型是推导出来的函数
- Constexpr语言 - 为什么只是一个返回语句
- 如何创建一个返回护士函数的函数
- 如何用C包装一个返回智能指针的C++函数
- 如何使用两个函数,一个返回迭代器,另一个返回const_iterator