本人是用 C# 实现的,其它 高级语言 同理。
// 存放所有的敏感词
public static string[] senseWords = { "脱衣", "爱你"};
public static string ReplaceSenseWord(string str) {
/*
* 由于后面有大量的字符串变化,因此通过使用 StringBuilder 来减少一点消耗
* sb 用于最后修改使用
* utilSb 用于前面查询敏感词使用
* findIndex 临时存储查到的敏感词索引
*
* 使用一个键值对类型来进行索引存储,键为敏感词,值为一个列表,
* 用于存储当前敏感词的所有索引,只有第一个为真实索引,后面的所有索引为
* 小于等于当前索引的所有 索引和 加上 敏感词的长度
*
* 查询时遍历所有的敏感词,判断 utilSb 中是否含有该敏感词,utilSb 每重新循环一次
* 都要去除上一次的索引加上当前敏感词的长度
* 当前敏感词查询完后要将 utilSb 重新填充为目标字符串
*
* 修改时先遍历所有的键值对,根据每一个键值对的值(列表)的个数来
* 得到键(敏感词)在目标字符串中出现的个数,然后根据值(列表)得出每个
* 真实索引,将其替换为 *,替换长度为当前敏感词的长度
*/
StringBuilder sb = new StringBuilder(str);
StringBuilder utilSb = new StringBuilder();
int findIndex;
Dictionary<string, List<int>> dic = new Dictionary<string, List<int>>();
// 查询
foreach (string senseWord in senseWords) {
// 重新填充目标字符串
utilSb.Clear();
utilSb.Append(sb);
while (utilSb.ToString().Contains(senseWord)) {
if (dic.ContainsKey(senseWord) == false) {
dic.Add(senseWord, new List<int>());
}
findIndex = utilSb.ToString().IndexOf(senseWord);
dic[senseWord].Add(findIndex);
// 删除从零开始,长度为 findIndex + senseWord.Length 的字符串
utilSb.Remove(0, findIndex + senseWord.Length);
}
}
// 修改
foreach (KeyValuePair<string, List<int>> kv in dic) {
for (int i = 0; i < kv.Value.Count; i++) {
for (int j = 0; j < kv.Key.Length; j++) {
int tempIndex = GetSumIndex(kv.Value, i, kv.Key.Length);
// 设置替换的字符
sb[tempIndex + j] = '*';
}
}
}
return sb.ToString();
}
public static int GetSumIndex(List<int> list, int count, int senseWordLen) {
/*
* 用于返回当前敏感词的第 count 个的真实索引
*/
int sum = 0;
for (int i = 0; i <= count; i++) {
if (i == 0) {
sum = list[i];
} else {
sum += list[i] + senseWordLen;
}
}
return sum;
}