引用空间:System.Text.RegularExpression
在名字空间中仅仅包含着6个类和一个委托,它们是:
Capture: 包含一次匹配的结果;
CaptureCollection: Capture的序列;
Group: 一次组记录的结果,由Capture继承而来;
Match: 一次表达式的匹配结果,由Group继承而来;
MatchCollection: Match的一个序列;
MatchEvaluator: 执行替换操作时使用的代理;
Regex: 编译后的表达式的实例。
Regex类中还包含一些静态的方法:
Escape(): 对字符串中的regex中的转义符进行转义;
IsMatch(): 如果表达式在字符串中匹配,该方法返回一个布尔值;
Match(): 返回Match的实例;
Matches(): 返回一系列的Match的方法;
Replace(): 用替换字符串替换匹配的表达式;
Split(): 返回一系列由表达式决定的字符串;
Unescape():不对字符串中的转义字符转义。
六个类详解:
Capture:
// 摘要: 原始字符串中发现捕获的子字符串的第一个字符的位置。 // 返回结果:原始字符串中发现捕获的子字符串的从零开始的起始位置。 public int Index { get; } // 摘要: 捕获的子字符串的长度。 // 返回结果: 捕获的子字符串的长度。 public int Length { get; } // 摘要:从输入字符串中获取捕获的子字符串。 // 返回结果:通过匹配捕获的实际子字符串。 public string Value { get; } // 摘要:从输入字符串中获取捕获的子字符串。 // 返回结果: 通过匹配捕获的实际子字符串。 public override string ToString(); |
CaptureCollection:Capture的序列
// 摘要:获取由该组捕获的子字符串数。 //返回结果:CaptureCollection 中的项数。 public int Count { get; } // 摘要: i:捕获集合中的索引。 // 返回结果:位于集合中 i 位置的捕获子字符串。 public Capture this[int i] { get; } // 摘要:将集合的所有元素复制到给定数组array中,(从array的给定索引处开始插入)。 public void CopyTo(Array array, int arrayIndex); |
Group:
// 摘要:按从里到外、从左到右的顺序获取由捕获组匹配的所有捕获的集合(如果正则表达式用 System.Text.RegularExpressions.RegexOptions.RightToLeft。选项修改了,则顺序为按从里到外、从右到左)。该集合可以有零个或更多的项。 // 返回结果:由该组匹配的子字符串的集合。 public CaptureCollection Captures { get; } // 摘要:获取一个值,该值指示匹配是否成功。 // 返回结果:如果匹配成功,则为 true;否则为 false。 public bool Success { get; } // 摘要:返回一个与提供的对象等效的 Group 对象,在多个线程间共享该对象是安全的。 // 返回结果:一个正则表达式 Group 对象。这个多线程操作的时候比较重要 public static Group Synchronized(Group inner); |
Match:
{ // 摘要:获取空组。所有失败的匹配都返回此空匹配。 // 返回结果:一个空 System.Text.RegularExpressions.Match。 public static Match Empty { get; } // 摘要:获取由正则表达式匹配的组的集合。 // 返回结果:由模式匹配的字符组。 public virtual GroupCollection Groups { get; } // 摘要:从上一个匹配结束的位置开始返回一个包含下一个匹配结果的新 Match。 // 返回结果:下一个正则表达式 Match 对象。 public Match NextMatch(); // 摘要:返回对指定替换模式的扩展。 // 参数:replacement:要使用的替换模式。 // 返回结果:replacement 参数的扩展版本。 public virtual string Result(string replacement); // 摘要:返回一个与提供的实例等效的 Match 实例,该实例适合在多个线程间共享。 // 参数:inner:一个与预期的实例等效的 Match 实例。 // 返回结果:一个与提供的实例等效的 Match 实例,该实例适合在多个线程间共享。 public static Match Synchronized(Match inner); |
MatchCollection:
// 摘要:获取捕获数。 // 返回结果:捕获数。 public int Count { get; } // 摘要:获取该集合的i索引处的单个成员。 // 返回结果:位于集合中 i 位置的捕获子字符串。 public virtual Match this[int i] { get; } // 摘要:将集合的所有元素复制到给定数组array,从arrayIndex开始插入。 public void CopyTo(Array array, int arrayIndex); |
MatchEvaluator委托:
// 摘要:表示在 Overload:System.Text.RegularExpressions.Regex.Replace 方法操作过程中每当找到正则表达式匹配时都调用的方法。 // 返回结果: // 由 System.Text.RegularExpressions.MatchEvaluator 委托表示的方法返回的字符串。 [Serializable] public delegate string MatchEvaluator(Match match); |
Regex:
// 摘要:指示 System.Text.RegularExpressions.Regex 构造函数中指定的正则表达式在输入字符串中是否找到匹配项。 public bool IsMatch(string input); // 摘要:指示 System.Text.RegularExpressions.Regex 构造函数中指定的正则表达式从输入字符串的指定起始位置开始是否找到匹配项。 public bool IsMatch(string input, int startat); // 摘要:指示正则表达式使用 pattern 参数中指定的正则表达式是否在输入字符串中找到匹配项。 public static bool IsMatch(string input, string pattern); // 摘要:在指定的输入字符串中搜索 System.Text.RegularExpressions.Regex 构造函数中指定的正则表达式匹配项。 public Match Match(string input); // 摘要:从指定的输入字符串起始位置开始在输入字符串中搜索正则表达式匹配项。 public Match Match(string input, int startat); // 摘要:在指定的输入字符串中搜索 pattern 参数中提供的正则表达式的匹配项。 // 返回结果:一个正则表达式 System.Text.RegularExpressions.Match 对象。 public static Match Match(string input, string pattern); // // 摘要:从指定的输入字符串起始位置开始在输入字符串中搜索具有指定输入字符串长度的正则表达式匹配项。 public Match Match(string input, int beginning, int length); //此处也同上,具有一类类似方法 public MatchCollection Matches(string input); //在指定的输入字符串内,使用指定的替换字符串替换与某个正则表达式模式匹配的所有字符串。 public string Replace(string input, string replacement); //在指定的输入字符串内,使用 System.Text.RegularExpressions.MatchEvaluator 委托返回的字符串替换与某个正则表达式模式匹配的字符串(其数目为指定的最大数目)。 public string Replace(string input, MatchEvaluator evaluator, int count); public static string Replace(string input, string pattern, MatchEvaluator evaluator); // 摘要: // 在由 System.Text.RegularExpressions.Regex 构造函数中指定的正则表达式定义的位置,将指定的输入字符串拆分指定的最大次数。 public string[] Split(string input, int count); |
在c#中实战:
替换:
public void Replace(){ string source = "刘备ABC关羽ABc张飞Abc赵云abc诸葛亮aBC孙权abC周瑜AbC鲁肃"; Regex regex = new Regex("abc", RegexOptions.IgnoreCase); string result = regex.Replace(source, "|"); } |
(转载别人的图片)
上图是需要注意的。这个正则表达式里面包含了四个group。默认为从左到右的方式匹配,所以查询得出来的最外面的MatchCollection 里面包含的每一个Match都是group[0]所示意的整个分组,对于Match.Groups又依次包含下面的几个子查询。其中索引为0的子查询其实就是本身。
贪婪算法:
目标:不追求最优解,只希望得到较为满意解。
适用场景:简单问题,问题的解决方案的独立型好
定义:是采用逐步构造最优解的方法,即在每一个阶段,都做出一个看上去最优的决策;决策一旦做出,就不可再更改。
结构:
候选方案(CandidateSet)有一套可以解决问题的候选方案
选择函数(SelectionFunction)选择最优候选方案
可行性函数(FeasibilityFunction)确定是否可用某个候选方案
目标函数(ObjectiveFunction)用于判定整体的或者某个阶段的结果好坏
结果函数(SolutionFunction)用于结束
示例:
4件物品,其重量分别为w=[2,4,6,7],要求从中取出几件物品装入背包,且总重量不能超过c=7。
解决方案:
C#代码实现如下:
商品对象:
private class Goods { int _weight; //商品重量 int _value; //商品价值 } |
贪婪算法实现体:
static int[] GreedyAlgorithm(int p_condition, Goods[] p_goods) { int[] res; //构造结果存储器,并初始化该器件 Range();//按照重量贪婪原则进行排序 //贪婪算法主体 int weightTotal = 0; for (int i = 0; i < p_goods.Length; i++) { if ((weightTotal += p_goods[i].Weight) > p_condition) //条件装箱操作 break; res[i] = 1; } return res; //返回结果 } |
方法调用:
static void Main(string[] args) { Goods[] goods = new Goods[] { new Goods(2), new Goods(4), new Goods(6), new Goods(7) }; int heightCondition = 7; int[] res = GreedyAlgorithm(heightCondition,goods); Write();//输出结果 } |
输出结果:
上例解决的是最简单的贪婪例子,但实际应用中,这类简单的问题比例比较小,我们很多时候遇到的是np问题,例如,在上面的例子中为商品加入价值属性,我们将目标函数改成价值总和最大,那么我们上面的解决方案将失效。为此我们不得不引入k阶贪婪算法,其实k阶贪婪算法并不是什么新概念,其实就是数学上面的子集使用而已。
例如对于n的贪婪问题,k阶贪婪算法的子集个数其实就是而已。例如对于上面的例子,k=0时,则子集为null,后面直接使用一般贪婪法就是我们上面的解决方案,当k=1的时候,我们就具有{1}{2}{3}{4}四个子集,以每一个子集为第一个进箱,然后按照np中的密度算法将其余非递减排序后直接使用一般贪婪算法思想既可以。如果k=2,那么子集就是六个,{1,2}{1,3}{1,4}{2,3}{2,4}{3,4}。那么k=3的也类似,k=4那么就是全部了。其实如果你遍历k=0到k=n的所有情况,那么运算次数其实就是2的n次方。如果运用递归选择最优解的话,那么运行次数将是n的阶乘。当随着n增大的时候,那么贪婪法的优势将会越来越明显,因为贪婪法的事件耗费是指数增长,而遍历的时间耗费是阶乘增长,完全不是一个量级的。所以除非逼不得已的情况下,例如物理上面求解波函数的时候,以势能作为目标函数的时候,那么只能球的精确解,因为波的原因,精确解与近似解的x差距可能十万步千里,最终的图谱将会完全不同,这个时候只能求最优解,至于算法,主要就是惩罚函数的算法了,那个在数值解法里面由很详细的说明。