关键词: KMP算法 随机数组 闭包与全局变量
在我作校园教育类小程序前期,曾做过一个关于单词搜索的功能,那个大体的逻辑便是采用的KPM算法,并且对于当今前端来说最‘吃香’的算法就是KMP,甚至大家只要接触字符匹配与匹配度大小等相关逻辑功能的搭建一定第一想到的就是KMP算法,它的主要特点就是在你获取的字符充当一个节点,在你输入时的长度就相当于输出节点的长度,在匹配的过程就是,在第一个节点开始计算,第一个为0,如果第一个字符与已知正确字符相等,就命名第二节点为1,如果不相等依然记为0,最后节点长度/输入长度便是整串字符的匹配度,如果按照匹配度优先原则进行对已知获取的数据进行重新排列组合,得到的结果一定是输入时得到的结果,当然在搜索页面KMP算法占有了绝大的优势!
大概代码就是如下:(C++来着百度百科)
#include
#include
using namespace std;
inline void NEXT(const string&T, vector<int>&next){//按模式串生成vector,next(T.size())
next[0] = -1;
for (int i = 1; i<T.size(); i++){
int j = next[i - 1];
while (j >= 0 && T[i - 1] != T[j]) j = next[j];//递推计算
if (j >= 0 && T[i - 1] == T[j]) next[i] = j + 1;
else next[i] = 0;
}
}
inline string::size_type COUNT_KMP(const string&S, const string&T){
//利用模式串T的next函数求T在主串S中的个数count的KMP算法
//其中T非空,
vector<int>next(T.size());
NEXT(T, next);
string::size_type index, count = 0;
for (index = 0; index<S.size(); ++index){
int pos = 0;
string::size_type iter = index;
while (pos<T.size() && iter<S.size()){
if (S[iter] == T[pos]){ ++iter; ++pos; }
else{
if (pos == 0) ++iter;
else pos = next[pos - 1] + 1;
}
}
if (pos == T.size() && (iter - index) == T.size()) ++count;
}
return count;
}
int main(int argc, char*argv[])
{
string S="abaabcacabaabcacabaabcacabaabcacabaabcac";
string T="ab";
//cin >> S;
//cin >> T;
string::size_type count = COUNT_KMP(S, T);
cout << count << endl;
system("PAUSE");
return 0;
}
我为什么要介绍KPM算法?
在背单词时,通常的逻辑就是,首先要从数据库内把数据随机拿出一条,并将数据与输入/选择的单词进行匹配,如果数据与输入单词是同一个词,那么说明输入正确,否则错误提示正确单词,点击下一词依此类推。在匹配过程就需要字符与字符的匹配,但对于背单词来说,匹配的逻辑稍稍与KMP算法有一点差异,因为背单词是在你输入/选择完成后才能与获取的数据进行匹配,即为KMP的逆逻辑。
既然已经想通了背单词的逻辑,那么首先就先对数据库进行获取随机数据,在这里我们以云开发作为小程序后台与前端衔接。根据官方文档内提到有关与随机数据的便是sample()函数根据相关文档说明
看出只要运用sample()函数根据规则设置随机数量size大小就可以获取到相关随机数据,具体如下代码:
const db = wx.cloud.database()
db.collection('database')
.aggregate() //aggreate下使用sample
.sample({
size: 1, //随机数量为1个
})
.end() //获取完成
.then(res => {
this.setData({
list: res.list //刷新数据
}
console.log(res) //打印数据至控制台
)
})
在上面代码中then(res=>{})内根据函数的构造形成了关于then()函数的闭包,当res获取的数组在外引用时便会报错
thirdScriptError: res is not defined...
为了解决这个问题为了让数据从then(res=>{})闭包内传到外面,我们在这里采用全局变量的方式,将res内数据传到外面。
即
//index.js
//顶头需要引入getApp()函数即:const app = getApp()
.then(res => {
this.setData({
list: res.list //刷新数据
}
console.log(res) //打印数据至控制台
let words = res.list[0].value//value是具体数据
app.globalData.words = words
console.log(app.globalData.words)
)
})
//app.js
APP({
//...
this.globalData = {}
//...
})
既然已经可以将数据库内数据取出来并可以引入到输入函数内,那么最后输入监视与结果检查便已经水到渠成了
首先需要在输入框内绑定函数getInput()
<input bindInput='getInput' style="color:{{colors}}"/>/*此处省略部分代码*/
然后在index.js内进行对输入框进行监视并使用KMP算法的逻辑对其进行检查与提示,具体如下代码:
data:{
colors :'',
}
getInput: function (e) {
var word = this.data.word
if (e.detail.value == app.globalData.words) {
wx.showToast({
title: '回答对了呢!',
icon: 'success'
})
this.setData({
colors: 'rgb(40, 247, 33)'
})
}
if (e.detail.value.length == app.globalData.words.length) {
if (e.detail.value != app.globalData.words) {
wx.showToast({
title: '不对呀,看看正确答案~',
icon: 'none'
})
this.setData({
word: app.globalData.words,
colors: 'rgb(247, 33, 33)'
})
}
}
console.log(e)
}
在背单词时,如果你设置的是输入框,在用户没有输入单词的情况是没办法知道这个单词的正确拼写的,那么如果遇到了一个并不认识的单词并且无法拼写的情况,我们作为开发者一定会想到加入提示功能,点击提示按钮
查看单词拼写,以达到背诵单词的目的,增加用户使用的舒适度。
好了不墨迹太多话语了,千言万语也比不上贴代码。
getWord: function(e){
if(app.globalData.words ===undefined){
app.globalData.words = '点击查看以查看单词拼写'
}
wx.showToast({
title: app.globalData.words,
icon: 'none'
})
}