#include<iostream> #include<unordered_set> using namespace std; string a,b; int n; unordered_set<string> st; inline bool check(int l,int r){ for(register int i=0;i<n;i++){ if(a[i]==b[l]){ l++; } if(l>r){ return true; } } return false; } inline string strc(int l,int r){ string s=""; for(register int i=l;i<=r;i++){ s+=b[i]; } return s; } signed main(){ cin.sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n>>a>>b; bool flag=1; for(int i=0;i+1<n;i++){ if(b[i]!=b[i+1]){ flag=0; } } if(flag){ cout<<n; return 0; } int sum=0; for(register int i=0;i<n;i++){ for(register int j=i;j<n;j++){ string s=strc(i,j); if(check(i,j)&&!st.count(strc(i,j))){ sum++; st.insert(s); } } } cout<<sum; return 0; }
时间: 2023-07-14 15:10:11 浏览: 90
这段代码是一个字符串匹配的问题。它的功能是统计字符串 b 中有多少个连续子串与字符串 a 完全匹配。代码首先将字符串 a 和 b 读入,并创建一个 unordered_set 用于记录已经匹配过的子串。
然后,代码通过遍历字符串 b 的所有可能的起始和结束位置,将其所对应的子串与字符串 a 进行匹配。匹配的过程是通过一个 check 函数来完成的,它会逐个比较字符串 a 和 b 的字符,如果匹配成功,就将指针 l 向右移动,直到整个字符串 a 都被匹配完。如果在匹配过程中,指针 l 超过了指针 r,说明匹配成功。
如果匹配成功且当前子串还没有被记录在集合 st 中,就将子串加入集合 st,并将计数器 sum 加一。
最后,输出计数器 sum 的值,即为与字符串 a 完全匹配的子串个数。
请问有什么其他问题我可以帮助你解答的吗?
相关问题
给#include <iostream>#include <string>#include <unordered_set>using namespace std;string removeDuplicates(string s) { unordered_set<char> seen; string result = ""; for (char c : s) { if (seen.count(c) == 0) { seen.insert(c); result += c; } } return result;}int main() { string input = "hello world"; string output = removeDuplicates(input); cout << output << endl; return 0;}封装
以下是封装后的代码:
```
#include <iostream>
#include <string>
#include <unordered_set>
using namespace std;
class DuplicatesRemover {
public:
DuplicatesRemover() {}
~DuplicatesRemover() {}
string removeDuplicates(string s) {
unordered_set<char> seen;
string result = "";
for (char c : s) {
if (seen.count(c) == 0) {
seen.insert(c);
result += c;
}
}
return result;
}
};
int main() {
string input = "hello world";
DuplicatesRemover remover;
string output = remover.removeDuplicates(input);
cout << output << endl;
return 0;
}
```
在这个封装的代码中,我们创建了一个 `DuplicatesRemover` 类,其中包含了一个公有的 `removeDuplicates()` 函数,用于去除字符串中的重复字符。
这个类的构造函数和析构函数都是空的,因为在这个例子中,我们没有需要初始化或清理的数据。
在 `removeDuplicates()` 函数中,我们使用了一个无序集合 `seen` 来存储已经出现过的字符。对于输入字符串中的每个字符,我们首先检查它是否已经在 `seen` 集合中出现过。如果没有,我们将其加入到 `seen` 集合中,并将其加入到结果字符串 `result` 中。最后,我们返回 `result` 字符串。
在 `main()` 函数中,我们创建了一个 `DuplicatesRemover` 对象 `remover`,并使用它的 `removeDuplicates()` 函数去除了字符串中的重复字符。最后,我们将结果输出到控制台。
优化这段代码#include <iostream> #include <iomanip> #include <stdio.h> #include <fstream> #include <string> #include <algorithm> #include <unordered_map> #include <map> #include <stack> #include <set> #include <vector> using namespace std; struct Production { char left; // 产生式的左部非终结符 string right; // 产生式的右部字符串 }; map<char, set<char>> firstSets; int main() { vector<Production> productions; ifstream infile("grammar.txt"); char left; string right; while (infile >> left >> right) { productions.push_back({ left, right }); } for (auto p : productions) { char left = p.left; string right = p.right; char firstChar = right[0]; if (isupper(firstChar)) { // 如果是非终结符 // 计算非终结符的first集合 set<char> firstSet = firstSets[firstChar]; for (int i = 0; i < right.length(); i++) { char ch = right[i]; if (isupper(ch)) { // 如果是非终结符 firstSet.insert(firstSets[ch].begin(), firstSets[ch].end()); if (firstSets[ch].find('$') == firstSets[ch].end()) { // 如果该非终结符没有空串 break; } } else { // 如果是终结符 firstSet.insert(ch); break; } } firstSets[left].insert(firstSet.begin(), firstSet.end()); } else { // 如果是终结符 firstSets[left].insert(firstChar); } } for (auto p : productions) { char left = p.left; cout << "First(" << left << ") = {"; for (auto ch : firstSets[left]) { cout << ch << ", "; } cout << "}" << endl; } }使得能正确求出frist集
以下是优化后的代码:
```c++
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
using namespace std;
// 产生式结构体
struct Production {
char left; // 产生式的左部非终结符
string right; // 产生式的右部字符串
};
// 计算first集合
set<char> calcFirstSet(char ch, const vector<Production>& productions, map<char, set<char>>& firstSets) {
// 如果该字符已经计算过first集合,直接返回
if (firstSets.find(ch) != firstSets.end()) {
return firstSets[ch];
}
set<char> result;
// 遍历所有产生式,查找该字符作为左部的产生式
for (auto p : productions) {
if (p.left == ch) {
// 如果右部第一个字符是终结符,则加入该字符
if (!isupper(p.right[0])) {
result.insert(p.right[0]);
}
// 如果右部第一个字符是非终结符,则计算该非终结符的first集合
else {
set<char> subResult = calcFirstSet(p.right[0], productions, firstSets);
result.insert(subResult.begin(), subResult.end());
// 如果该非终结符的first集合中包含空串,则计算下一个字符的first集合
for (int i = 1; i < p.right.length() && subResult.find('$') != subResult.end(); i++) {
if (!isupper(p.right[i])) {
result.insert(p.right[i]);
break;
} else {
subResult = calcFirstSet(p.right[i], productions, firstSets);
result.insert(subResult.begin(), subResult.end());
}
}
}
}
}
// 将计算得到的first集合插入到map中
firstSets.insert(make_pair(ch, result));
return result;
}
int main() {
vector<Production> productions;
ifstream infile("grammar.txt");
// 读取产生式
char left;
string right;
while (infile >> left >> right) {
productions.push_back({ left, right });
}
map<char, set<char>> firstSets;
// 计算每个非终结符的first集合
for (auto p : productions) {
if (isupper(p.right[0])) {
set<char> result = calcFirstSet(p.left, productions, firstSets);
firstSets.insert(make_pair(p.left, result));
} else {
firstSets.insert(make_pair(p.left, set<char>{p.right[0]}));
}
}
// 输出每个非终结符的first集合
for (auto p : productions) {
char left = p.left;
cout << "First(" << left << ") = {";
for (auto ch : firstSets[left]) {
cout << ch << ", ";
}
cout << "}" << endl;
}
}
```
优化后的代码主要是将计算first集合的部分提取出来,封装成了一个函数`calcFirstSet`。在计算每个非终结符的first集合时,只需调用该函数进行计算即可。同时,在计算非终结符的first集合时,使用了递归的方式,可以很方便地计算出包含空串的情况。
阅读全文